提问人:Sydney Loteria 提问时间:12/22/2016 最后编辑:Mayank Kumar ChaudhariSydney Loteria 更新时间:2/2/2023 访问量:199593
setState 不会立即更新状态 [duplicate]
setState doesn't update the state immediately [duplicate]
问:
我想问一下为什么当我做一个活动时,我的状态没有改变。我刚才搜索过我需要在构造函数中绑定函数,但状态仍然没有更新。onClick
onClick
这是我的代码:
import React from 'react';
import Grid from 'react-bootstrap/lib/Grid';
import Row from 'react-bootstrap/lib/Row';
import Col from 'react-bootstrap/lib/Col';
import BoardAddModal from 'components/board/BoardAddModal.jsx';
import style from 'styles/boarditem.css';
class BoardAdd extends React.Component {
constructor(props) {
super(props);
this.state = {
boardAddModalShow: false
};
this.openAddBoardModal = this.openAddBoardModal.bind(this);
}
openAddBoardModal() {
this.setState({ boardAddModalShow: true }); // set boardAddModalShow to true
/* After setting a new state it still returns a false value */
console.log(this.state.boardAddModalShow);
}
render() {
return (
<Col lg={3}>
<a href="javascript:;"
className={style.boardItemAdd}
onClick={this.openAddBoardModal}>
<div className={[style.boardItemContainer,
style.boardItemGray].join(' ')}>
Create New Board
</div>
</a>
</Col>
);
}
}
export default BoardAdd
答:
您的状态需要一些时间来改变,并且由于在状态改变之前执行,因此您可以获得前一个值作为输出。所以你需要在函数的回调中写控制台console.log(this.state.boardAddModalShow)
setState
openAddBoardModal() {
this.setState({ boardAddModalShow: true }, function () {
console.log(this.state.boardAddModalShow);
});
}
setState
是异步的。这意味着您不能在一行上调用它,并假设状态在下一行已更改。
根据 React 文档
setState()
不会立即变异,但会创建一个 挂起状态转换。调用此项后访问 方法可能会返回现有值。没有 保证对 setState 的调用的同步操作,并且调用可能 进行批处理以提高性能。this.state
this.state
他们为什么要异步setState
这是因为会更改状态并导致重新渲染。这 可能是一项代价高昂的操作,使其同步可能会离开 浏览器无响应。
setState
因此,调用是异步的,也是批处理的,以便更好地进行 UI 体验和性能。
setState
评论
幸运的是,需要回调。这就是我们获得更新状态的地方。setState()
请看这个例子。
this.setState({ name: "myname" }, () => {
//callback
console.log(this.state.name) // myname
});
因此,当回调触发时,this.state 是更新后的状态。
您可以在回调中获取数据。mutated/updated
评论
initMap()
由于 setSatate 是一个异步函数,因此您需要像这样将状态作为回调进行控制台。
openAddBoardModal(){
this.setState({ boardAddModalShow: true }, () => {
console.log(this.state.boardAddModalShow)
});
}
如果要跟踪状态是否正在更新,那么执行相同操作的另一种方法是
_stateUpdated(){
console.log(this.state. boardAddModalShow);
}
openAddBoardModal(){
this.setState(
{boardAddModalShow: true},
this._stateUpdated.bind(this)
);
}
这样,每次尝试更新调试状态时,都可以调用该方法“_stateUpdated”。
这个回调真的很乱。只需改用 async await:
async openAddBoardModal(){
await this.setState({ boardAddModalShow: true });
console.log(this.state.boardAddModalShow);
}
评论
setState
setState
await new Promise(resolve => this.setState({ boardAddModalShow: true }, () => resolve()))
async this.setState({})
setState()
并不总是立即更新组件。它可能会批处理或推迟更新,直到以后。这使得在调用后立即阅读 this.state 成为潜在的陷阱。请改用 use 或 callback (),保证在应用更新后触发其中任何一个。如果需要根据以前的状态设置状态,请阅读下面的 updater 参数。setState()
componentDidUpdate
setState
setState(updater, callback)
setState()
将始终导致重新渲染,除非返回 false。如果正在使用可变对象,并且无法在 中实现条件渲染逻辑,则仅当新状态与先前状态不同时调用将避免不必要的重新渲染。shouldComponentUpdate()
shouldComponentUpdate()
setState()
第一个参数是带有签名的更新程序函数:
(state, props) => stateChange
state
是对应用更改时组件状态的引用。它不应该被直接突变。相反,更改应该通过基于 state 和 props 的输入构建一个新对象来表示。例如,假设我们想通过 props.step 增加 state 中的值:
this.setState((state, props) => {
return {counter: state.counter + props.step};
});
setState()
是异步的。验证状态是否正在更新的最佳方法是在 而不是放在 之后。componentDidUpdate()
console.log(this.state.boardAddModalShow)
this.setState({ boardAddModalShow: true })
根据 React Docs
将 setState() 视为一个请求,而不是更新组件的即时命令。为了获得更好的感知性能,React 可能会延迟它,然后在一次传递中更新多个组件。React 不保证立即应用状态更改
this.setState({
isMonthFee: !this.state.isMonthFee,
}, () => {
console.log(this.state.isMonthFee);
})
评论
根据 React Docs
React 不保证状态更改会立即应用。 这使得在调用 setState() 后立即读取 this.state 成为一种可能性,并且由于性质的原因,可能会返回值。 请改用 或 setState 操作成功后立即执行的回调。通常,我们建议改用此类逻辑。
pitfall
existing
async
componentDidUpdate
setState
componentDidUpdate()
例:
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
class App extends React.Component {
constructor() {
super();
this.state = {
counter: 1
};
}
componentDidUpdate() {
console.log("componentDidUpdate fired");
console.log("STATE", this.state);
}
updateState = () => {
this.setState(
(state, props) => {
return { counter: state.counter + 1 };
});
};
render() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<button onClick={this.updateState}>Update State</button>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
是的,因为 setState 是一个异步函数。在编写 set state 后立即设置状态的最佳方法是使用 Object.assign,如下所示: 例如,您要将属性 isValid 设置为 true,请像这样操作
Object.assign(this.state, { isValid: true })
您可以在编写此行后立即访问更新的状态。
评论
当我运行代码并在控制台检查我的输出时,它显示它未定义。 在我四处搜索并找到对我有用的东西之后。
componentDidUpdate(){}
我在 constructor() 之后的代码中添加了此方法。 查看 React Native 工作流的生命周期。
https://images.app.goo.gl/BVRAi4ea2P4LchqJ8
对于任何尝试使用钩子执行此操作的人,您需要 .useEffect
function App() {
const [x, setX] = useState(5)
const [y, setY] = useState(15)
console.log("Element is rendered:", x, y)
// setting y does not trigger the effect
// the second argument is an array of dependencies
useEffect(() => console.log("re-render because x changed:", x), [x])
function handleXClick() {
console.log("x before setting:", x)
setX(10)
console.log("x in *line* after setting:", x)
}
return <>
<div> x is {x}. </div>
<button onClick={handleXClick}> set x to 10</button>
<div> y is {y}. </div>
<button onClick={() => setY(20)}> set y to 20</button>
</>
}
输出:
Element is rendered: 5 15
re-render because x changed: 5
(press x button)
x before setting: 5
x in *line* after setting: 5
Element is rendered: 10 15
re-render because x changed: 10
(press y button)
Element is rendered: 10 20
将 视为请求,而不是立即命令 更新组件。为了获得更好的感知性能,React 可以 延迟它,然后在一次传递中更新多个组件。反应 不保证立即应用状态更改。
setState()
有关详细信息,请查看此内容。
在您的情况下,您已发送更新状态的请求。React 需要时间来响应。如果尝试立即进入状态,则将获得旧值。console.log
尽管有很多好的答案,但如果有人登陆此页面,寻找实现 UI 组件(如导航抽屉)的替代方案,这些组件应根据用户输入打开或关闭,则此答案将有所帮助。useState
虽然看起来很方便,但状态不会立即设置,因此,您的网站或应用程序看起来很滞后......如果你的页面足够大,react 将需要很长时间来计算在状态更改时应该更新哪些内容......useState
我的建议是,当您希望 UI 立即更改以响应用户操作时,请使用 refs 并直接操作 DOM。
在反应的情况下,将状态用于此目的确实是一个坏主意。
上述解决方案不适用于 useState 钩子。 可以使用以下代码
setState((prevState) => {
console.log(boardAddModalShow)
// call functions
// fetch state using prevState and update
return { ...prevState, boardAddModalShow: true }
});
评论
setMyVariable(false)
评论
setState
await