gpt4 book ai didi

javascript - 状态更新可能是异步的

转载 作者:行者123 更新时间:2023-12-04 00:59:24 25 4
gpt4 key购买 nike

它们到底是什么意思?如果我理解 it正确,我不能使用 this.state计算新状态时,除非我将函数作为第一个参数传递给 setState() :

// Wrong
this.setState({a: f(this.state)});

// Correct
this.setState(prevState => {return {a: f(prevState)}});

但我可以使用 this.state决定做什么:
if (this.state.a)
this.setState({b: 2});

Prop 呢?
// Correct or wrong?
this.setState({name: f(this.props)});

据说我不能指望 this.state调用 this.setState后更改:
this.setState({a: 1});
console.log(this.state.a); // not necessarily 1

然后,假设我有一个用户列表。还有一个我可以让一个用户成为当前用户的选择:
export default class App extends React.Component {
...

setCurrentUserOption(option) {
this.setState({currentUserOption: option});
if (option)
ls('currentUserOption', option);
else
ls.remove('currentUserOption');
}

handleAddUser(user) {
const nUsers = this.state.users.length;
this.setState(prevState => {
return {users: prevState.users.concat(user)};
}, () => {
// here we might expect any number of users
// but if first user was added, deleted and added again
// two callbacks will be called and setCurrentUserOption
// will eventually get passed a correct value

// make first user added current
if ( ! nUsers)
this.setCurrentUserOption(this.userToOption(user));
});
}

handleChangeUser(user) {
this.setState(prevState => {
return {users: prevState.users.map(u => u.id == user.id ? user : u)};
}, () => {
// again, we might expect any state here
// but a sequence of callback will do the right thing
// in the end

// update value if current user was changed
if (_.get(this.state, 'currentUserOption.value') == user.id)
this.setCurrentUserOption(this.userToOption(user));
});
}

handleDeleteUser(id) {
this.setState(prevState => {
return {users: _.reject(prevState.users, {id})};
}, () => {
// same here

// choose first user if current one was deleted
if (_.get(this.state, 'currentUserOption.value') == id)
this.setCurrentUserOption(this.userToOption(this.state.users[0]));
});
}

...
}

应用批量更改状态后,是否按顺序执行所有回调?

再三考虑, setCurrentUserOption基本上就像 setState .它将更改排入 this.state .即使按顺序调用回调,我也不能依赖 this.state被之前的回调改变了,可以吗?所以最好不要提取 setCurrentUserOption方法:
handleAddUser(user) {
const nUsers = this.state.users.length;
this.setState(prevState => {
let state = {users: prevState.users.concat(user)};
if ( ! nUsers) {
state['currentUserOption'] = this.userToOption(user);
this.saveCurrentUserOption(state['currentUserOption']);
}
return state;
});
}

saveCurrentUserOption(option) {
if (option)
ls('currentUserOption', option);
else
ls.remove('currentUserOption');
}

这样我就可以对 currentUserOption 的更改进行排队免费。

最佳答案

你并没有真正问一个非常具体的问题。 “这是什么意思”并不多说。但是您通常似乎了解基础知识。

有两种方法可以调用setState() : 要么传递一个对象以合并到新状态,要么传递一个函数,该函数返回一个对象,该对象以类似于第一种方式的方式合并。

所以你要么这样做:

// Method #1
this.setState({foo: this.state.foo + 1}, this.someCallback);

或这个:
// Method #2
this.setState((prevState) => {return {foo: prevState.foo + 1}}, this.someCallback);

主要区别在于方法#1, foo将根据您调用 setState() 时的状态加 1 , 而在方法 #2 中, foo将根据箭头函数运行时的先前状态加 1。因此,如果您有多个 setState()在实际状态更新之前的“同一”时间发生的调用,使用方法#1它们可能会发生冲突和/或基于过时的状态,而使用方法#2它们保证具有最新状态,因为它们在状态更新阶段一个接一个地同步更新。

这是一个说明性示例:

Method #1 JSBIN Example
// Method #1
class App extends React.Component {
constructor(props) {
super(props);
this.state = {n: 0};
this.increment.bind(this);
}
componentDidMount() {
this.increment();
this.increment();
this.increment();
}
increment() {
this.setState({n: this.state.n + 1}, () => {console.log(this.state.n)});
}
render() {
return (
<h1>{this.state.n}</h1>
);
}
}

React.render(
<App />,
document.getElementById('react_example')
);

在上面:您会在控制台中看到:
> 1
> 1
> 1

this.state.n 的最终值将是 1 .所有 setState()n 的值时,调用已入队是 0 ,所以它们都简单地设置为 0 + 1 .

Method #2 JSBIN Example
// Method #2
class App extends React.Component {
constructor(props) {
super(props);
this.state = {n: 0};
this.increment.bind(this);
}
componentDidMount() {
this.increment();
this.increment();
this.increment();
}
increment() {
this.setState((prevState) => {return {n: prevState.n + 1}}, () => {console.log(this.state.n)});
}
render() {
return (
<h1>{this.state.n}</h1>
);
}
}

React.render(
<App />,
document.getElementById('react_example')
);

在上面,您会在控制台中看到:
> 3
> 3
> 3

n 的最终值将是 3 .与方法 #1 一样,所有 setState()调用同时排队。然而,由于他们使用函数来同步更新以使用最新状态 - 包括由并发状态更新对状态所做的更改 - 他们正确地递增 n是你预期的三倍。

现在,为什么 console.log()显示 3方法 #2 的三次,而不是 1 , 2 , 3 ?答案是 setState()回调都在 React 的状态更新阶段结束时一起发生,而不是在特定状态更新发生之后立即发生。所以在这方面方法#1 和#2 是相同的。

关于javascript - 状态更新可能是异步的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45248204/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com