简体   繁体   English

如何从需要访问 state 的 React Hooks 返回 function?

[英]How to return a function from React Hooks that need access to the state?

I'm building a custom hook to manage the data coming from a fetch/axios/promise/whateveryouwant function, this hooks allow me to update the data whenever I want using an update function that I return at the end of my hook.我正在构建一个自定义钩子来管理来自 fetch/axios/promise/whateveryouwant function 的数据,这个钩子允许我随时使用我在钩子末尾返回的更新 function 更新数据。

So for now I have two states inside my hooks:所以现在我的钩子中有两个状态:

const [data, setData] = useState<T>(defaultValue); // the data coming from the fetch, T is defined by the user of the hook
const [query, setQuery] = useState<Array<{ key: string; value: string }>>([]); // array of query option for the URL

I wanted to implement a dynamic way to add query string to the URL, so I used the query state to have an array of object representing what I wanted but I cannot access the value of the query inside of the update function when calling from outside. I wanted to implement a dynamic way to add query string to the URL, so I used the query state to have an array of object representing what I wanted but I cannot access the value of the query inside of the update function when calling from outside. Here is the hooks, I highlited the important part:这是钩子,我强调了重要的部分:

export default function useFetchV2<T>(
  defaultValue: T,
  getData: (queryString?: string) => Promise<T>
): {
  update: () => void;
  data: T;
  updateQueryValue: (key: string, value: string) => void; // update, data, updateQueryValue are the return value of the hook.
} {
  const [data, setData] = useState<T>(defaultValue);
  const [query, setQuery] = useState<Array<{ key: string; value: string }>>([]); // THE STATE I WANT TO ACCESS

  console.log(query, data); // Here the state is updating well and everything seems fine

  const update = useCallback((): void => {
    let queryString;

    console.log(query, data);

   // But here is the problem, query and data are both at their default value. The state inside the hooks is correct but not here.

    if (query.length > 0) { // query.length always at 0
      queryString = _.reduce(
        query,
        (acc, el) => {
          return `${acc}${el.key}=${el.value.toString()}`;
        },
        '?'
      );
      console.log(queryString);
    }
    getData(queryString).then(res => setData(res));
  }, [data, getData, query]);

  const updateQueryValue = useCallback(
    (key: string, value: string): void => {
      const index = query.findIndex(el => el.key === key);
      if (index !== -1) {
        if (!value) {
          const toto = [...query];
          _.pullAt(toto, index);
          setQuery(toto);
        } else {
          setQuery(prev =>
            prev.map(el => {
              if (el.key === key) {
                return { key, value };
              }
              return el;
            })
          );
        }
      } else {
        console.log(key, value); // everything is logging well here, good key and value
        setQuery([...query, { key, value }]); // setQuery correctly update the state
      }
      update();
    },
    [query, update]
  );

  useEffect(() => {
    update();
  }, []);

  return { update, data, updateQueryValue };
}

It might be the way I'm exporting the function, I'm still not used to the scope.这可能是我导出function的方式,我仍然不习惯scope。

I called updateQueryValue from a component.我从一个组件中调用了 updateQueryValue。 The function is called, state is changed, but the update function can't see the difference.调用了function,改了state,但是更新function看不出区别。

The code is calling setQuery and then immediately calling update and expecting query to be updated value, but it will always be the current value of query .代码调用setQuery然后立即调用update并期望query是更新的值,但它始终是query当前值。 Getting that to happen is the use case of useEffect .实现这一点是useEffect的用例。

  } else {
    console.log(key, value); // everything is logging well here, good key and value
    setQuery([...query, { key, value }]); // setQuery correctly update the state
  }
  
  // This will *always* see the current value of `query`, not the one that
  // was just created in the `else` block above.
  update();
  1. It sounds like the code should run update after query is updated, which is exactly what useEffect is for.听起来代码应该在query update ,这正是useEffect的用途。
const updateQueryValue = useCallback(
    (key: string, value: string): void => {
      const index = query.findIndex(el => el.key === key);
      if (index !== -1) {
        if (!value) {
          const toto = [...query];
          _.pullAt(toto, index);
          setQuery(toto);
        } else {
          setQuery(prev =>
            prev.map(el => {
              if (el.key === key) {
                return { key, value };
              }
              return el;
            })
          );
        }
      } else {
        setQuery([...query, { key, value }]); // setQuery correctly update the state
      }

      // This call isn't needed, it will always "see" the old value of
      // `query`
      // update();
    },
    [query, update]
  );

  // Call `update` once when this custom hook is first called as well as
  // whenever `query` changes.
  useEffect(() => {
    update();
  }, [query]); // <-- this is new, add `query` as a dependency
  1. useCallback is only needed if something is relying on the identity of the function to make decisions; useCallback仅在依赖 function 的身份做出决定时才需要; eg if a component receives the function as a prop, it checks whether the prop changes to decide whether to re-render.例如,如果一个组件接收到 function 作为 prop,它会检查 prop 是否发生变化以决定是否重新渲染。 update in this case does not need a useCallback and might make this hook slightly harder to debug.在这种情况下update不需要useCallback并且可能会使这个钩子更难调试。
function update() {
    let queryString;
    if (query.length > 0) { // query.length always at 0
      queryString = _.reduce(
        query,
        (acc, el) => {
          return `${acc}${el.key}=${el.value.toString()}`;
        },
        '?'
      );
      console.log(queryString);
    }
    getData(queryString).then(res => setData(res));
  });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何从 function 内部访问我的反应钩子 state - How can I access my react hooks state from inside a function 如何使用来自异步函数返回的 React 挂钩设置 state - How to set state with React hooks from async fucntion return React:如何使用React Hooks在Function组件内部添加onChange功能? 需要复选框中的onClick事件以影响输入状态 - React: How to add onChange functionality inside of Function component using React Hooks? Need onClick event from a checkbox to influence input state Strange React挂钩行为,无法从函数中访问新状态 - Strange React hooks behavior, can't access new state from a function React hooks,将函数的返回值设置为 state 会导致无限循环 - React hooks, set return value of a function to state causes infinite loop 如何在 React 中访问孩子的状态? (反应钩子) - How to access child's state in React? (React Hooks) 反应钩子 - 在 function 中更新 State - React hooks - Update State in function 搜索表 React Hooks 后如何返回旧的 state - How to return to old state after searching table React Hooks 使用 React Hooks 卸载组件时如何访问状态? - How to access state when component unmount with React Hooks? 如何在使用反应挂钩的 setState 方法之后访问更新的 state? - How to access the updated state after setState method with react hooks?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM