簡體   English   中英

在 React 中更改全局狀態時,子組件導致父組件渲染過多

[英]Child component causing too many renderings on parent component when changing global state in React

我正在開發一個 React Web 應用程序,我有一個用於存儲一些數據的全局狀態,出於某種原因,我碰巧在我的應用程序上看到了不必要的渲染!

我有看起來像這樣的組件:

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>
          ))}
      }
  </>
  )
}

這個組件導致父組件在沒有從這個組件做任何動作的情況下渲染,因為一旦組件被安裝(至少我知道),調度函數會立即在useEffect()內部調用,我還能如何處理這個所以只調度當我單擊單選按鈕時被調用? 一旦使用setState()更改本地狀態,是否有任何回調或某種方式可以調用 dispatch ?

知道在這種情況下如何使用調度嗎?

更新這一行

<GreenCheckbox onChange={handleChange(lang.term)} value="checked" />

對此

<GreenCheckbox onChange={() => handleChange(lang.term)} value="checked" />

您正在渲染時調用該函數。 給它一個回調

更新:

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,
      },
    })
 }

經過幾次嘗試,我想出了這個,對我來說似乎很好,不會導致父組件重新渲染!

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>
          ))}
        </>
      )}
    </>
  )
}

不確定它是否正確,但任務完成了!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM