如何在UseEffect中使用prop函数?

时间:2020-06-19 06:26:49

标签: javascript reactjs frontend lint

我想在UseEffect内调用prop函数。以下代码有效:

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

但是,皮棉抱怨props不是依赖项。

如果执行此操作,则该代码将不再起作用,并且出现最大的重新渲染错误:

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

如何解决棉绒问题?

示例代码:

父组件

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}
      />

子组件

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

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

5 个答案:

答案 0 :(得分:0)

添加props.handleClick作为依赖项

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

答案 1 :(得分:0)

您应该在道具之外破坏handleClick

在组件开始时,您可能会遇到类似这样的情况:

const myComponent = (props) =>

更改为

const myComponent = ({ handleClick, id })基本上,您可以拔出任何已知为道具的道具

然后像下面这样使用:

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

或者您可能实际上并不需要该函数作为依赖项,所以应该可以使用

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

答案 2 :(得分:0)

this为空调用函数,如下所示:

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

只要props.handleClick不指向使用this.的函数或方法,一切都应能按预期工作。

答案 3 :(得分:0)

执行此操作的一种正确方法是添加 props.handleClick 作为依赖项并记住父级上的 handleClick (useCallback),以便函数引用不会在重新渲染之间发生不必要的更改。

通常不建议关闭 lint 规则,因为它可以帮助解决细微的错误(当前和未来)

在您的情况下,如果您从 deps 数组中排除 handleClick,并且在父级上,该函数依赖于父级道具或状态,则当父级道具或状态发生更改时,您的 useEffect 将不会触发,尽管应该如此,因为handleClick 函数现已更改。

答案 4 :(得分:0)

我在这里看到很多奇怪和不正确的答案,所以我觉得有必要写下这个。

将函数添加到依赖项数组时达到最大调用深度的原因是它没有稳定的标识。在 React 中,如果您不将其包装在 useCallback 钩子中,则在每次渲染时都会重新创建函数。这将导致 react 在每次渲染时看到您的函数发生变化,从而每次都调用您的 useEffect 函数。

一种解决方案是将函数包装在 useCallback 中它在父组件中定义的位置,并将其添加到子组件中的依赖项数组中。使用您的示例,这将是:

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]);
};

(假设父组件中的 rows props 在每次渲染时都不会改变)