使用 React Hooks,使用 "useState" 和 "useEffect",有没有办法渲染状态等待状态有值?
Using React Hooks, using "useState" and "useEffect", is there a way to render a state waiting till the state has a value?
我想做什么?
通过 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
甚至决定设置任何内容之前尝试渲染。
您可以调整您的 return 语句以仅呈现名称 if/when 它存在
return (
<div>
{characterInfo.length && characterInfo.models[0].name}
</div>
)
I think the front-end tries to render before setCharacterInfo decides to even set anything.
没错,在 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({});
我想做什么?
通过 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
甚至决定设置任何内容之前尝试渲染。
您可以调整您的 return 语句以仅呈现名称 if/when 它存在
return (
<div>
{characterInfo.length && characterInfo.models[0].name}
</div>
)
I think the front-end tries to render before setCharacterInfo decides to even set anything.
没错,在 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({});