【问题标题】:Using React Hooks, using "useState" and "useEffect", is there a way to render a state waiting till the state has a value?使用 React Hooks,使用“useState”和“useEffect”,有没有办法渲染一个状态,直到状态有一个值?
【发布时间】:2020-09-23 23:15:59
【问题描述】:

我想做什么?

通过 React Hooks 将 characterInfo 渲染到前端。

目前尝试这样做的代码是什么?

呈现信息的前端组件:

export default function ReactComponent() {
  const [characterInfo, setCharacterInfo] = useState([]);

  useEffect(() => {
    socket.emit("/character/read");
    socket.on("/character/read", function (data) {
      if (data.status === "SUCCESS") {
        setCharacterInfo(data)
      }
    });
    return () => {
      socket.off("/character/read");
    };
  }, []);

  return (
    <div>
      {characterInfo.models[0].name}
    </div>
  )
}

后端.json信息作为“数据”以及setCharacterInfo保存到characterInfo的内容:

{
  status: "SUCCESS"
  models: [
    { 
      name: "AC",
      element: "Air",
    }
    {
      name: "Irene",
      element: "Fire",
    }
  ]
}

(所以在这种情况下访问“AC”,它将是characterInfo.models[0].name

我期望结果是什么?

我希望只呈现AC

实际结果如何?

我会收到这个错误:

TypeError: Cannot read property '0' of undefined

我认为问题可能是什么?

我认为它必须处理异步平衡,尤其是useEffect()。我认为前端会在 setCharacterInfo 决定设置任何内容之前尝试渲染。

【问题讨论】:

  • 你需要遍历你的结果。在渲染时使用类似“地图”的东西
  • 另外,当您的状态设置为 characterInfo 时,您的设置数据作为您状态的一部分
  • 对于第一条评论,如果你说 {characterInfo.models.map((model) =&gt; (&lt;div&gt;{model.name}&lt;/div&gt;))},我会收到的错误是 TypeError: Cannot read property 'map' of undefined'. 对于第二条评论,是的,我将“数据”放入 setCharacterInfo 作为状态,那么“数据”应该是我characterInfo状态。

标签: javascript reactjs react-hooks use-effect use-state


【解决方案1】:

我认为前端会在 setCharacterInfo 决定设置任何内容之前尝试渲染。

没错,在运行useEffect 中的函数之前,您的组件会使用默认的useState 值渲染一次。下面是组件挂载、更新和卸载时的执行顺序图(注意render 发生在useEffect 之前):

https://raw.githubusercontent.com/donavon/hook-flow/master/hook-flow.png

在访问name 之前,您需要检查characterInfo.models 是否存在(为了安全起见,请确保它有一个长度)。

  return (
    <div>
      {
        characterInfo.models &&
        characterInfo.models.length &&
        characterInfo.models[0].name
      }
    </div>
  )

或者,如果您使用的是可选链接:

  return (
    <div>
      {characterInfo?.models[0]?.name}
    </div>
  )

另一个注意事项 - 您将 characterInfo 的初始值设置为一个空数组。如果将其设为空对象,则更清楚的是您期望 data 是一个对象,而不是一个数组。

const [characterInfo, setCharacterInfo] = useState({});

【讨论】:

  • 我尝试了第一个解决方案,前端没有渲染任何东西。我为每个值都做了一个console.log,接下来是:[{...}], undefined, "AC"。现在,当我简单地尝试{characterInfo.models &amp;&amp; characterInfo.models[0].name} 时,它起作用了!我尝试了第二种解决方案,它导致了与TypeError: Cannot read property '0' of undefined 相同的问题。我继续做了你的笔记,我认为这有助于利用。感谢您的帮助!
【解决方案2】:

您可以调整您的 return 语句以仅在名称存在时/当它存在时呈现名称

return (
    <div>
      {characterInfo.length && characterInfo.models[0].name}
    </div>
  )

【讨论】:

  • 该解决方案对我不起作用,我深入了解通过console.log(characterInfo.length)console.log(characterInfo.models[0].name) 的按钮显示了哪些值,第一个将显示undefined,第二个将显示"AC"。感谢您的尝试!
猜你喜欢
  • 1970-01-01
  • 2020-01-06
  • 1970-01-01
  • 2020-02-24
  • 2019-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-26
相关资源
最近更新 更多