简体   繁体   English

在 React 中更改全局状态时,子组件导致父组件渲染过多

[英]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.

相关问题 反应-将状态传递给父组件-太多AXIOS请求 - React - Passing state to parent component - too many AXIOS requests 当父组件更新时,React阻止子组件中的更改状态 - React prevent change state in child component when parent component update 更新父组件 state 时反应子组件不重新渲染 - React child component not rerendering when updating parent component state REACT - REDUX 如何更新子组件中 redux 应用程序的全局状态,子组件在安装应用程序时在父组件中获取数据 - REACT - REDUX how to update the global state of a redux app in child component that fetched data in parent when app is mounted React - 当父级更改时更新子组件中的 state - React - update state in the child component when parent changes 在 React 的父组件中触发动作时获取子状态 - Get child state when the action is triggered in parent component in React 当 React 中的父状态发生变化时重新渲染子组件 - Rerendering child component when parent state changes in React React:更改子组件后如何正确更新父组件的 state - React: How to properly update state of parent component after changing child component 尝试在响应中将父状态传递给子组件 - Trying to pass a parent state to child component in react 反应子组件不更新父状态 - React child component not updating parent state
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM