如何在 useEffect 钩子中正确实现 props 回调函数

bsh*_*ook 4 reactjs eslint create-react-app react-hooks

我想用来useEffect()检测状态值的变化,并使用作为道具接收的回调函数将该值传递给父组件。如果不禁用 eslint 缺少依赖项警告,我无法找到一种方法。我在子组件和那个孩子的孩子上都有这个问题。

这是父实现:

const updateValues = (newValues) => {
  setValues({ ...values, ...newValues });
};

<GeneralUpdates onUpdate={updateValues} />
Run Code Online (Sandbox Code Playgroud)

这是第一个孩子(GeneralUpdates):

const [values, setValues] = useState({
    name: '',
    description: '',
  });

// This handles form input changes
const handleChange = (prop) => (event) => {
  setValues({ ...values, [prop]: event.target.value });
};

useEffect(() => {
  onUpdate(values);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [values]);

<FilesUpload handleChange={onUpdate}/>

Run Code Online (Sandbox Code Playgroud)

这是孩子的孩子(文件上传):

const [featuredPhotos, setFeaturedPhotos] = useState([]);

useEffect(() => {
  handleChange({ featuredPhotos });
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [featuredPhotos]);
Run Code Online (Sandbox Code Playgroud)

添加handleChange为依赖项会导致无限重新渲染循环。我已经尝试了我能找到的所有解决方案,但这里一定遗漏了一些东西。

bsh*_*ook 5

一位同事帮我找到了解决方案——将命名函数传递给 useEffect 而不是匿名函数:

const updateCallback = () => {
    onUpdate(values);
  };

useEffect(updateCallback, [values]);
Run Code Online (Sandbox Code Playgroud)

  • 需要注意的一件事是,这基本上禁用了依赖项列表的 eslint 检查。例如,如果您从依赖项中删除值参数,它不会抱怨。 (3认同)

Shu*_*tri 3

如果您 100% 知道自己在做什么,则针对此特定规则禁用 eslint 没有任何问题。

但是,如果父组件是功能组件,您仍然可以通过使用从父组件传递的函数来解决useCallback hook此问题,而无需禁用 eslinthandleChange

// in parent
const handleChange = useCallback(({featuredPhotos}) => {
    // Do what you want to do here
}, []);
Run Code Online (Sandbox Code Playgroud)

如果父级不是功能组件,请确保在渲染中没有使用箭头函数,同时将其作为道具传递,应该没问题

handleChange = ({featuredPhotos}) => {
   ...
}

render() {
   return (
       <Child handleChange={this.handleChange} />
   )
}
Run Code Online (Sandbox Code Playgroud)

编辑:

对于您的情况,您可以使用 updateValue 函数的 useCallback 来更新实现,并在其中使用函数 setState

const updateValues = useCallback((newValues) => {
  setValues(prevValues => ({ ...prevValues, ...newValues }));
}, []);
Run Code Online (Sandbox Code Playgroud)