【问题标题】:How do I fetch data in a React custom hook only once?如何仅在 React 自定义挂钩中获取数据一次?
【发布时间】:2020-04-21 13:07:17
【问题描述】:

我有一个自定义钩子,它可以获取 许多 组件使用的本地 JSON 文件。

hooks.js

export function useContent(lang) {
    const [content, setContent] = useState(null);

    useEffect(() => {
        const abortController = new AbortController();
        const signal = abortController.signal;

        fetch(`/locale/${lang}.json`, { signal: signal })
            .then((res) => {
                return res.json();
            })
            .then((json) => {
                setContent(json);
            })
            .catch((error) => {
                console.log(error);
            });

        return () => {
            abortController.abort();
        };
    }, [lang]);

    return { content };
}

/components/MyComponent/MyComponent.js

import { useContent } from '../../hooks.js';

function MyComponent(props) {
  const { content } = useContent('en');
}

/components/MyOtherComponent/MyOtherComponent.js

import { useContent } from '../../hooks.js';

function MyOtherComponent(props) {
  const { content } = useContent('en');
}

我的组件行为相同,因为我在两者中都将相同的en 字符串发送到我的useContent() 挂钩。 useEffect() 应该仅在 lang 参数更改时运行,因此看到两个组件使用相同的 en 字符串,useEffect() 应该只运行一次 ,但它没有 - 它运行多次。这是为什么?如何更新我的钩子,使其仅在 lang 参数更改时获取?

【问题讨论】:

  • 鉴于这似乎是一个共享状态,你为什么不使用上下文?

标签: reactjs react-hooks fetch-api use-effect


【解决方案1】:

钩子在不同的组件中独立运行(以及在相同组件类型的不同实例中)。所以每次在新组件中调用useContent,效果(获取数据)都会运行一次。 (正如 React 所承诺的那样,同一组件的重复渲染不会重新获取数据。)相关:React Custom Hooks fetch data globally and share across components?

在许多组件之间共享状态的通用 React 方法是使用 Context 挂钩 (useContext)。更多关于上下文here。你会想要这样的东西:

const ContentContext = React.createContext(null)

function App(props) {
  const { content } = useContent(props.lang /* 'en' */);
  return (
    <ContentContext.Provider value={content}>
      <MyComponent>
      <MyOtherComponent>
  );
}

function MyComponent(props) {
  const content = useContext(ContentContext);
}

function MyOtherComponent(props) {
  const content = useContext(ContentContext);
}

这样,如果您想更新内容/语言/其他内容,您可以在应用级别(或您认为有意义的任何更高级别)执行此操作。

【讨论】:

    猜你喜欢
    • 2020-06-20
    • 2023-01-21
    • 1970-01-01
    • 2021-10-26
    • 1970-01-01
    • 2022-01-27
    • 2022-01-07
    • 2021-07-18
    • 2021-11-22
    相关资源
    最近更新 更多