简体   繁体   English

如何在 UseEffect 中使用道具 function?

[英]How to use a prop function inside of UseEffect?

I want to call a prop function inside of UseEffect.我想在 UseEffect 中调用一个道具 function。 The following code works:以下代码有效:

useEffect(() => {
    props.handleClick(id);
  }, [id]);

But lint is complaining about props not being a dependency.但是 lint 抱怨props不是依赖项。

If I do this, then the code no longer works and I have maximum re-render error:如果我这样做,那么代码将不再有效,并且我有最大的重新渲染错误:

  useEffect(() => {
        props.handleClick(id);
      }, [id, props]);

How can I fix the lint issue?如何解决棉绒问题?

Sample code:示例代码:

Parent Component父组件

const ParentGrid = ({rows, columns}) => {

  const [selection, setSelection] = useState(null);

  const handleClick = selectedRows => {
    setSelection(selectedRows.map(i => rows[i]));
  };

  return (
      <ChildGrid
        columns={columns}
        data={data}
        handleClick={handleClick}
      />

Child Component子组件

const ChildGrid = props => {
  const {data, handleClick, ...rest} = props;

  useEffect(() => {
    handleClick(selectedRows);
  }, [selectedRows]);

you should destructure handleClick outside of props你应该在道具之外解构handleClick

at the start of the component you probably have something like this:在组件的开头你可能有这样的东西:

const myComponent = (props) =>

change to改成

const myComponent = ({ handleClick, id }) basically you can pull out any props you know as their actual name const myComponent = ({ handleClick, id })基本上你可以取出任何你知道的道具作为它们的实际名称

then use below like so:然后像这样使用下面:

useEffect(() => {
    handleClick(id);
  }, [id, handleClick]);

or probably you don't actually need the function as a dependency so this should work或者您可能实际上并不需要 function 作为依赖项,所以这应该可以工作

useEffect(() => {
    handleClick(id);
  }, [id]);

Call the function with this as null, like so:使用 null 调用 function, this所示:

useEffect(() => {
    props.handleClick.call(null, id);
}, [id, props.handleClick]);

Everything should work as expected as long as props.handleClick doesn't point to a function or a method that uses this.只要 props.handleClick 不指向 function 或使用this. . .

One correct way to do this is to add props.handleClick as a dependency and memoize handleClick on the parent (useCallback) so that the function reference does not change unnecessarily between re-renders.一种正确的方法是添加props.handleClick作为依赖项并在父项(useCallback)上记忆 handleClick,以便 function 引用不会在重新渲染之间不必要地更改。

It is generally NOT advisable to switch off the lint rule as it can help with subtle bugs (current and future)通常不建议关闭 lint 规则,因为它可以帮助解决细微的错误(当前和未来)

in your case, if you exclude handleClick from deps array, and on the parent the function was dependent on parent prop or state, your useEffect will not fire when that prop or state on the parent changes, although it should, because the handleClick function has now changed. in your case, if you exclude handleClick from deps array, and on the parent the function was dependent on parent prop or state, your useEffect will not fire when that prop or state on the parent changes, although it should, because the handleClick function has现在改变了。

I see alot of weird and incorrect answers here so I felt the need to write this.我在这里看到很多奇怪和不正确的答案,所以我觉得有必要写这个。

The reason you are reaching maximum call depth when you add the function to your dependency array is because it does not have a stable identity.将 function 添加到依赖项数组时达到最大调用深度的原因是因为它没有稳定的标识。 In react, functions are recreated on every render if you do not wrap it in a useCallback hook.在反应中,如果您不将函数包装在useCallback挂钩中,则会在每次渲染时重新创建函数。 This will cause react to see your function as changed on every render, thus calling your useEffect function every time.这将导致反应看到您的 function 在每次渲染时都已更改,因此每次都调用您的 useEffect function。

One solution is to wrap the function in useCallback where it is defined in the parent component and add it to the dependency array in the child component.一种解决方案是将 function 包装在useCallback中,它在父组件中定义,并将其添加到子组件中的依赖数组中。 Using your example this would be:使用您的示例,这将是:

const ParentGrid = ({rows, columns}) => {
  const [selection, setSelection] = useState(null);

  const handleClick = useCallback((selectedRows) => {
    setSelection(selectedRows.map(i => rows[i]));
  }, [rows]); // setSelection not needed because react guarantees it's stable

  return (
    <ChildGrid
      columns={columns}
      data={data}
      handleClick={handleClick}
    />
  );
}

const ChildGrid = props => {
  const {data, handleClick, ...rest} = props;

  useEffect(() => {
    handleClick(selectedRows);
  }, [selectedRows, handleClick]);
};

(This assumes the rows props in parent component does not change on every render) (这假设父组件中的rows道具在每次渲染时都不会改变)

Add props.handleClick as the dependency添加props.handleClick作为依赖

useEffect(() => {
  props.handleClick(id);
}, [id, props.handleClick]);

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM