[英]React useMemo dependency loop with state and onChange
在下面的代碼中FormExample
正在呈現。 Form
is a 是SampleTextField
的包裝器,用於處理所有子字段的更改和 state。 我正在嘗試使用useMemo
以便一個字段的更改不會重新呈現另一個字段。
The problem is that the handleChange
function is cached with its state
scope so if I change the first field, and then edit the second the state is overwritten with the old value of the first field.
我可以在useCallback
中添加 wrap handleChange ,但它只會與它引用的 onChange 產生相同的問題。
我也嘗試將handleChange 添加到useMemo 的依賴數組中,但是因為在每個state 更改(因為重新渲染)上都會創建一個新的handleChange 實例(因為重新渲染),所以它與沒有useMemo 相同。
有沒有我可以用來解決這個問題的模式?
import {TextField} from '@material-ui/core';
import * as React from 'react';
import {useContext, useState} from 'react';
const FormContext = React.createContext<any>({});
const Form = ({state, onChange, children}: any) => {
const handleChange = (name: any, val: any) => {
onChange({...state, [name]: val});
}
return (
<FormContext.Provider value={{state, handleChange}}>
{children}
</FormContext.Provider>
);
}
const SampleTextField = ({name}: any) => {
const {state, handleChange} = useContext(FormContext);
const value = state[name]
return React.useMemo(() => {
return (
<TextField name={name} value={value} onChange={(e: any) => handleChange(e.target.name, e.target.value)}/>
);
}, [value]);
}
const FormExample = () => {
const [state, setState] = useState({text1: "", text2: ""});
return (
<Form state={state} onChange={setState}>
<SampleTextField name="text1"/>
<br/><br/>
<SampleTextField name="text2"/>
</Form>
)
}
export default FormExample;
您可以使用useCallback
使您的handleChange
參考穩定。 請注意我如何使用setState
的 function 形式,它接受當前 state 作為第一個參數
import { TextField } from "@material-ui/core";
import * as React from "react";
import { useContext, useState, useMemo, useCallback, createContext } from "react";
const FormContext = createContext<any>({});
const Form = ({ state, onChange, children }: any) => {
const handleChange = useCallback(
(name: any, val: any) => {
onChange((state) => ({ ...state, [name]: val }));
},
[onChange]
);
const context = useMemo(
() => ({
state,
handleChange,
}),
[state, handleChange]
);
return (
<FormContext.Provider value={context}>{children}</FormContext.Provider>
);
};
const SampleTextField = ({ name }: any) => {
const { state, handleChange } = useContext(FormContext);
const value = state[name];
return useMemo(
() => (
<TextField
name={name}
value={value}
onChange={(e: any) => handleChange(e.target.name, e.target.value)}
/>
),
[value, handleChange]
);
};
const FormExample = () => {
const [state, setState] = useState({ text1: "", text2: "" });
return (
<Form state={state} onChange={setState}>
<SampleTextField name="text1" />
<br />
<br />
<SampleTextField name="text2" />
</Form>
);
};
export default FormExample;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.