道具更改不会触发useEffect

时间:2020-05-21 04:07:15

标签: reactjs react-props use-effect react-jsonschema-forms

我有一个带有useEffect的react组件,当props改变时不会被触发。我希望该组件根据道具更新其显示的内容。但是,当道具更改时,什么也没发生。

对于调试,我添加了一个按钮,该按钮可以手动更新值,效果很好。我只是无法获得useEffect来终生受益。

const ReadOnly = (props: WidgetProps) => {
    const [value, setValue] = React.useState('No Value');
    const { formContext } = props;

    const firstName = () => formContext.queryData[0]?.basicInformation?.firstName ?? 'No value';

    // This only runs once when the component is first rendered never fired when formContext updates.
    React.useEffect(() => {
        setValue(firstName());
    }, [formContext]);

    // This correctly updates the value
    const onClick = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
        e.preventDefault();
        setValue(firstName());
    };

    return (
        <>
            <p>{value}</p>
            <Button onClick={onClick}>Update Value</Button>
        </>
    );
};

export default ReadOnly;

我尝试将useEffect函数监视的值从formContext更改为formContext.queryData[0].basicInformation.firstName无效。我也尝试使用props代替。我什至尝试完全删除监视数组,希望它只是垃圾邮件更新,但什么也没有。

有关如何实现此目标的任何建议?我知道值正在传递到组件,因为当我按下按钮时它就起作用了。当我在网页上的React检查器中检出它时,我可以清楚地看到该值在那里。干杯。

编辑: 该组件被用作react-jsonschema-form的小部件。基本上,每次更新formData时,我都会将其传递回formContext中。 formContext是我可以向该小部件获取其他数据的唯一方法。下面是我正在做的精简版。

const [formDataAndIncludings, setFormDataAndIncludings] = React.useState<any>(null);

ClientRect.useEffect(() => {
    ...
    // Initial loading of formDataAndIncludings
    ...
}, [])

const onChange = (e: IChangeEvent<any>) => {
    const newFormDataAndIncludings = { ...formDataAndIncludings };
    newFormDataAndIncludings.queryData[0] = e.formData;
    setFormDataAndIncludings(newFormDataAndIncludings);
};

return (
    <Form
        ...
        onChange={onChange}
        formContext={formDataAndIncludings}
        ...
    />
)

1 个答案:

答案 0 :(得分:1)

状态直接在父级的onChange中突变,因此不会触发ReadOnly组件中的useEffect。

更新您的onChange

const onChange = (e: IChangeEvent<any>) => {
    setFormDataAndIncludings(prev => ({
            ...prev ,
            queryData : [
                e.formData,
                ...prev.queryData.slice(0,1)
            ]
        }))

    //const newFormDataAndIncludings = { ...formDataAndIncludings };
    //newFormDataAndIncludings.queryData[0] = e.formData;
    //setFormDataAndIncludings(newFormDataAndIncludings);
};

像往常一样提供useEffect依赖项

React.useEffect(() => {
        setValue(firstName());
    }, [formContext]);