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

时间:2020-07-09 05:10:59

标签: reactjs react-hooks create-react-app eslint

我想使用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}/>

这是孩子的孩子(FilesUpload):

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

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

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

3 个答案:

答案 0 :(得分:2)

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

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

useEffect(updateCallback, [values]);

答案 1 :(得分:0)

如果您知道100%在做什么,则为该特定规则禁用eslint不会有任何问题。

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

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

如果parent不是功能组件,请确保在将其作为道具传递时未在渲染中使用箭头功能,并且应该没事

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

render() {
   return (
       <Child handleChange={this.handleChange} />
   )
}

编辑:

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

const updateValues = useCallback((newValues) => {
  setValues(prevValues => ({ ...prevValues, ...newValues }));
}, []);

答案 2 :(得分:0)

我添加了另一种让 eslint 满意的解决方案:

const callback = useRef();
callback.current = onUpdate;     

useEffect(() => {
  callback.current(values);
}, [values, callback]);