我想使用useEffect()
来检测状态值的更改,并使用作为道具接收的回调函数将该值传递给父组件。如果不禁用eslint缺少依赖项警告,我想不出一种方法来做到这一点。我在子组件和该子组件上都有这个问题。
这是父实现:
const updateValues = (newValues) => {
setValues({ ...values, ...newValues });
};
<GeneralUpdates onUpdate={updateValues} />
这是第一个孩子(常规更新(:
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}/>
这是孩子的孩子(文件上传(:
const [featuredPhotos, setFeaturedPhotos] = useState([]);
useEffect(() => {
handleChange({ featuredPhotos });
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [featuredPhotos]);
添加handleChange
作为依赖项会导致无限的重新渲染循环。我已经尝试了所有我能找到的解决方案,但肯定遗漏了什么。
一位同事帮我找到了一个解决方案——将一个命名函数传递给useEffect,而不是匿名函数:
const updateCallback = () => {
onUpdate(values);
};
useEffect(updateCallback, [values]);
如果您100%知道自己在做什么,那么为这个特定规则禁用esint就没有任何问题。
但是,如果父级是功能组件,那么您仍然可以通过使用useCallback hook
来处理从父级传递的handleChange
函数,而不必禁用esint
// in parent
const handleChange = useCallback(({featuredPhotos}) => {
// Do what you want to do here
}, []);
如果父组件不是一个功能组件,请确保在将其作为道具传递时没有在渲染中使用箭头函数,并且您应该可以使用
handleChange = ({featuredPhotos}) => {
...
}
render() {
return (
<Child handleChange={this.handleChange} />
)
}
编辑:
对于您的案例,您可以使用useCallback for updateValue函数来更新实现,并在其中使用函数setState
const updateValues = useCallback((newValues) => {
setValues(prevValues => ({ ...prevValues, ...newValues }));
}, []);
我又添加了一个让eslint满意的解决方案:
const callback = useRef();
callback.current = onUpdate;
useEffect(() => {
callback.current(values);
}, [values, callback]);