说说竞态
上面是一个典型的在class组件里发申请的例子:
class Article extends Component {
state = {
article: null
};
componentDidMount() {
this.fetchData(this.props.id);
}
async fetchData(id) {
const article = await API.fetchArticle(id);
this.setState({ article });
}
// ...
}
你很可能曾经晓得,下面的代码潜伏了一些问题。它并没有解决更新的状况。所以第二个你可能在网上找到的经典例子是上面这样的:
class Article extends Component {
state = {
article: null
};
componentDidMount() {
this.fetchData(this.props.id);
}
componentDidUpdate(prevProps) { if (prevProps.id !== this.props.id) { this.fetchData(this.props.id); } } async fetchData(id) {
const article = await API.fetchArticle(id);
this.setState({ article });
}
// ...
}
这显然好多了!但仍旧有问题。有问题的起因是申请后果返回的程序不能保障统一。比方我先申请 {id: 10}
,而后更新到{id: 20}
,但{id: 20}
的申请更先返回。申请更早但返回更晚的状况会谬误地笼罩状态值。
这被叫做竞态,这在混合了async
/ await
(假如在期待后果返回)和自顶向下数据流的代码中十分典型(props和state可能会在async函数调用过程中产生扭转)。
Effects并没有神奇地解决这个问题,只管它会正告你如果你间接传了一个async
函数给effect。(咱们会改善这个正告来更好地解释你可能会遇到的这些问题。)
如果你应用的异步形式反对勾销,那太棒了。你能够间接在革除函数中勾销异步申请。
或者,最简略的权宜之计是用一个布尔值来跟踪它:
function Article({ id }) {
const [article, setArticle] = useState(null);
useEffect(() => {
let didCancel = false;
async function fetchData() {
const article = await API.fetchArticle(id);
if (!didCancel) { setArticle(article);
}
}
fetchData();
return () => { didCancel = true; }; }, [id]);
// ...
}
发表回复