[英]Child component causing too many renderings on parent component when changing global state in React
I am working on a React web application, I have a global state for storing some data, for some reason I happen to see quite unnecessarily renderings on my app!我正在开发一个 React Web 应用程序,我有一个用于存储一些数据的全局状态,出于某种原因,我碰巧在我的应用程序上看到了不必要的渲染!
I have component that looks like this:我有看起来像这样的组件:
const LanguageSkills = () => {
const [languageSelected, setLanguage] = React.useState({})
const { dispatch } = useContext(GlobalStore)
const handleChange = (name: string) => (event: any) => {
setLanguage({ ...languageSelected, [name]: event.target.checked })
}
useEffect(() => {
dispatch({
type: ApplicantActions.FILTER_APPLICANTS,
payload: {
languageSkills: languageSelected,
},
})
}, [dispatch, languageSelected])
return (
<>
{
{languageSkills.map((lang, index) => (
<TermWrapper key={index}>
<GreenCheckbox onChange={handleChange(lang.term)} value="checked" />
<Term>{lang.term}</Term>
</TermWrapper>
))}
}
</>
)
}
This component causes the parent component to render without any action doing from this component, well because the dispatch function is called immediately inside useEffect() once the component gets mounted (at least what I know), how else can I handle this so dispatch only gets called when I click the radio button?这个组件导致父组件在没有从这个组件做任何动作的情况下渲染,因为一旦组件被安装(至少我知道),调度函数会立即在useEffect()内部调用,我还能如何处理这个所以只调度当我单击单选按钮时被调用? Is there any callback or someway that I can call dispatch once the local state changed using setState() ?一旦使用setState()更改本地状态,是否有任何回调或某种方式可以调用 dispatch ?
Any idea how can I use dispatch in such situations?知道在这种情况下如何使用调度吗?
Update this line更新这一行
<GreenCheckbox onChange={handleChange(lang.term)} value="checked" />
to this对此
<GreenCheckbox onChange={() => handleChange(lang.term)} value="checked" />
you are calling the function in render time.您正在渲染时调用该函数。 give it a callback给它一个回调
UPDATED:更新:
const handleChange = (name: string) => (event: any) => {
setLanguage({ ...languageSelected, [name]: event.target.checked })
}
useEffect(() => {
callMe();
}, [languageSelected])
const callMe = () => {
dispatch({
type: ApplicantActions.FILTER_APPLICANTS,
payload: {
languageSkills: languageSelected,
},
})
}
After several trying I came up with this and it seems fine for me, does not cause anymore parent component to re-render!经过几次尝试,我想出了这个,对我来说似乎很好,不会导致父组件重新渲染!
const LanguageSkills = () => {
const [isVisible, setIsVisible] = useState(false)
const [state, setState] = React.useState({})
const { dispatch } = useContext(GlobalStore)
const handleChange = (name: string) => (event: React.ChangeEvent<HTMLInputElement>) => {
const obj = { ...state, [name]: event.target.checked }
dispatchLanguageFilter(obj)
setState({ ...state, [name]: event.target.checked })
}
const dispatchLanguageFilter = useCallback(
obj => {
const languageSkills: string[] = []
for (const [key, value] of Object.entries(obj)) {
if (value) {
languageSkills.push(key)
}
}
dispatch({
type: ApplicantActions.FILTER_APPLICANTS,
payload: {
languageSkills: languageSkills,
},
})
},
[dispatch],
)
return (
<>
<Wrapper onClick={() => setIsVisible(!isVisible)}>
<FilterContainerTitle>Kielitaito</FilterContainerTitle>
<Arrow>{!isVisible ? <ArrowDown /> : <ArrowUp />}</Arrow>
</Wrapper>
{isVisible && (
<>
{languageSkills.map((lang, index) => (
<TermWrapper key={index}>
<GreenCheckbox onChange={handleChange(lang.term)} value="checked" />
<Term>{lang.term}</Term>
<TotalAmountWrapper>
<TotalAmount>{lang.totalAmount}</TotalAmount>
</TotalAmountWrapper>
</TermWrapper>
))}
</>
)}
</>
)
}
Not sure if its right way but mission accomplished!不确定它是否正确,但任务完成了!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.