我想知道初始化状态并保持状态与服务器同步的最佳方式/模式是什么。在过去的几天里,我阅读和尝试了很多,但是没有发现任何解决我问题的方法。
这个例子真的很简单。为了简单起见,示例中有一种状态--它是一个数字,尽管在现实生活中它将是一个对象--我需要从服务器中检索它。一旦检索到,我希望它与服务器同步。getValueFromServer是一个模拟,它在setTimeout中等待随机时间之后返回一个随机值。
因此,要初始化我的状态,我使用空数组上的useEffect作为依赖项,为了保持同步,我使用状态作为依赖项的useEffect。
问题在于它试图保存一个未定义的值。日志如下。
1 ->首次初始化
2保存服务器值的-> API调用:未定义
3保存服务器值的-> API调用: 6.026930847574949
我得到的是:
1:按预期运行。
他说:这个我没料到。我想它是因为"useState“而触发的。
3:一旦从服务器获得响应,就运行。这很明显,但很痛苦,因为我到底为什么想要拯救这个。
这里最好的办法是什么?在带有依赖关系的useEffect中使用类似于“useEffect”标志的东西会让人感觉有点被黑了,而不是专业的。
下面的代码,您可以发现它也在这里工作:https://codesandbox.io/s/optimistic-rgb-uce9f
import React, { useState, useEffect } from "react";
import { getValueFromServer } from "./api";
export default function App() {
const [value, setValue] = useState();
useEffect(() => {
async function initialize() {
console.log("Initializing for first time");
let serverValue = await getValueFromServer();
setValue(serverValue);
}
initialize();
}, []);
useEffect(() => {
console.log("API call to save in server value: ", value);
}, [value]);
const handleClick = () => {
setValue(value + 1);
};
return (
<div className="App">
<h1>Value: {value}</h1>
<button onClick={handleClick}>Add 1 to value</button>
</div>
);
}发布于 2020-06-04 19:17:55
,这里最好的方法是什么?在带有依赖关系的useEffect中使用类似于“useEffect”标志的东西会让人感觉有点被黑了,而不是专业的。
您可以在useState中使用标志或使用默认值初始化对象。
const { Fragment, useState, useEffect } = React;
const getValueFromServer = () => new Promise((resolve, reject) => setTimeout(() => resolve(Math.random())), 1000)
const App = () => {
const [value, setValue] = useState(null);
const [isLoading, setLoading] = useState(true);
useEffect(() => {
let isUnmounted = false;
getValueFromServer().then(serverValue => {
console.log("Initializing for first time");
if(isUnmounted) {
return;
}
setValue(serverValue);
setLoading(false);
})
return () => {
isUnmounted = true;
}
}, []);
useEffect(() => {
if(!value) {
return () => {}
}
console.log("API call to save in server value: ", value);
setTimeout(() => setLoading(false), 50);
}, [value]);
const handleClick = () => {
setLoading(true);
setValue(value + 1);
};
return <div className="App">
{isLoading ? <Fragment>
<span>Loading...</span>
</Fragment> : <Fragment>
<h1>Value: {value}</h1>
<button onClick={handleClick}>Add 1 to value</button>
</Fragment>}
</div>
}
ReactDOM.render(
<App />,
document.getElementById('root')
);<script src="https://unpkg.com/react/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.10.1/polyfill.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<div id="root"></div>
发布于 2020-06-04 19:17:12
您的应用程序在忙着await处理第一个useEffect钩子函数中发生的事情时做其他的事情。本例中的“其他内容”是“执行第二个useEffect钩子函数”。此时没有定义serverValue,因此也没有定义value,因此console.log打印undefined。一旦您的await承诺解析为一个值并调用了setValue,您的第二个useEffect钩子函数的依赖项就会发生变化,导致您的函数再次运行(并打印出您期望的值)。
如果您必须有两个useEffect挂钩,那么当value未定义时,只需退出第二个钩子:
useEffect(() => {
if (value === undefined) {
return;
}
console.log('value is:', value);
}, [ value ]);https://stackoverflow.com/questions/62202159
复制相似问题