【问题标题】:Component doesn't re-render when props change using useState hook使用 useState 挂钩更改道具时组件不会重新渲染
【发布时间】:2020-03-12 06:39:52
【问题描述】:

每次我在 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,尽管每次数据道具都提供了新的更新值

【问题讨论】:

  • 请在您的控制台中显示错误。它会有有用的信息。
  • 你好@LongNguyen 我已经为这个错误感到安慰,它似乎重新渲染,但panelsData中的数据并没有改变每次它显示相同的结果,虽然数据道具给我更新的价值每-是时候更新我的问题以获取正确的查询了

标签: reactjs react-hooks


【解决方案1】:

你有没有尝试过 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.

【讨论】:

  • 你好@jdn我尝试使用上面的代码并安慰它似乎重新呈现的错误但是panelsData中的数据不会每次都改变它显示相同的结果尽管数据道具给了我每次更新的值
【解决方案2】:

如果您替换这部分代码,它会起作用吗?

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

【讨论】:

    【解决方案3】:

    这是因为当你这样做时:

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

    您只是将您的data 属性用作panelsData初始值。当 props 改变时,新数据将被忽略,因为panelsData 有自己的状态(嗯,它是一个 useState 钩子!)。

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

    如果您想观察 data 属性并相应地更新状态,您可以使用带有 datauseEffect 钩子作为依赖项(这意味着它只会在 data 更改时运行),例如这个:

    useEffect(() => {
      changePanel(data);
    }, [data]);
    

    【讨论】:

    • 非常感谢@ezakto,这正是我想要的,并回答了我的问题。
    • 完美解决了我的困扰。解释也很好。我不知道你可以像这样将 props 传递给 useEffect,我以为它只是状态。
    • @YungGun 您可以在依赖项数组中设置任何内容。当组件重新渲染时,它会检查数组的所有元素,看看是否至少有一个元素发生了变化,无论值来自哪里。
    • 绝妙的解决方案!我一直在想,“如果只有当道具改变时有一种本地方式来设置状态only。”这是漫长的一天......
    猜你喜欢
    • 2021-04-13
    • 1970-01-01
    • 1970-01-01
    • 2021-03-05
    • 1970-01-01
    • 2022-01-17
    • 1970-01-01
    • 2020-05-01
    • 2021-09-01
    相关资源
    最近更新 更多