使用useState挂钩更改道具时,组件不会重新渲染

时间:2019-11-16 07:04:15

标签: reactjs react-hooks

每次我在data prop中获取新数据,但组件不重新渲染,直到我调用handlePanelSelection()

function StepPanel({ data, getTranslations }) {
  const [panelsData, changePanel] = useState(data);

  function handlePanelSelection(panelId) {
    switch (panelId) {
      case 8:
        changePanel(getTranslations.NeeSubCategory);
        break;
      default:
        changePanel(data);
        break;
    }
  }
  return (
    <>
      {panelsData.map(details => {
        const imgsrc = requireContext('./' + details.image);
        return (
          <div key={details.id} className="block-list">
            <div className="left-block">
              <img src={imgsrc} alt="" />
            </div>
            <div className="right-block">
              <h3>{details.title}</h3>
              <p>{details.description}</p>
              <label htmlFor="radio1" className="radio-btn">
                <input
                  type="radio"
                  onClick={() => handlePanelSelection(details.id)}
                  name="radio1"
                />
                <span></span>
              </label>
            </div>
          </div>
        );
      })}
    </>
  );
}

但是当我像下面一样移除钩子时,

function StepPanel({ data, getTranslations }) {

  return (
    <>
      {data.map(details => { ... })}
    </>
         )
}

我想实现一种功能,当我在数据道具中获取新数据时,该组件将被重新渲染,但是当我需要在内部进行重新渲染时,例如像我更改panelId = 8时,它也会被重新渲染,

上面的代码似乎会重新渲染,但是每次都使用相同的数据,即,虽然每次为数据道具提供新的更新值,但每次都不会更新panelData

console image

3 个答案:

答案 0 :(得分:3)

这是因为当您这样做时:

const [panelsData, changePanel] = useState(data);

您仅将data道具用作panelsData初始值。当道具更改时,新数据将被忽略,因为panelsData有其自己的状态(嗯,这是一个useState挂钩!)。

这就是为什么您必须显式调用changePanel来更改状态的原因。 这就是整个想法!

如果您想观察data道具并相应地更新状态,则可以使用带有useEffect作为依赖项的data钩子(这意味着它仅在{ {1}}的更改),例如:

data

祝你好运!

答案 1 :(得分:0)

您是否曾经尝试过使用useEffect处理组件的重新渲染:

function handlePanelSelection(panelId) {
    switch (panelId) {
      case 8:
        changePanel(getTranslations.NeeSubCategory);
        break;
      default:
        changePanel(data);
        break;
    }
}
useEffect(() => {

}, [panelsData]) // just pass panelsData into here
// Component will re-render when panelsData change.

答案 2 :(得分:0)

如果您替换代码的这一部分,是否可行?

  // this block creates new function when re-render
  // replace
  function handlePanelSelection(panelId) {
    switch (panelId) {
      case 8:
        changePanel(getTranslations.NeeSubCategory);
        break;
      default:
        changePanel(data);
        break;
    }
  }
  // by
  const handlePanelSelection = useCallback(()=> {
    switch (panelId) {
      case 8:
        changePanel(getTranslations.NeeSubCategory);
        break;
      default:
        changePanel(data);
        break;
    }
  }, [data, getTranslations])