React - 状态未更新或重置为旧状态
React - State not updated or getting reset to old state
我正在尝试构建一个具有输入字段功能的聊天应用程序,它可以用作 chat_groups 数组的过滤器,该数组处于 chat_groups。这是我的代码的样子:
constructor(props) {
super(props);
this.state = {
currUserId: "--id--",
chats: [],
chat_groups: [],
users: [],
};
}
.
.
.
<input
className="chat-group__search__input"
placeholder="Search for group..."
onChange={(ev) => {
console.log(ev.currentTarget.value);
var thatState = this.state;
thatState.chat_groups = thatState.chat_groups.map(
(gp) => {
gp["visible"] = gp.group_name
.toLowerCase()
.includes(ev.currentTarget.value);
return gp;
}
);
// getting correct state in thatState variable
this.setState(thatState);
}}
/>
// getting old state in setState callback and componentDidUpdate lifecycle
奇怪的问题是我在设置状态之前在那个状态变量中得到了正确的值。但是在调用 setState 函数后,如果我尝试检查 setState 回调或 componentDidUpdate 生命周期中的状态,我只会得到旧状态。
我也为按键和更改事件尝试过。所以,似乎也不是事件的问题。
我想知道代码中是否存在明显的问题,或者我可以采取哪些措施来调试该问题。
编辑: 更改后,我当前的 onChange 如下所示,但问题仍然存在; setState 函数似乎没有改变状态,因为我只能在 componentDidUpdate 生命周期和 setState 回调中看到旧状态。
onChange={(ev) => {
console.log(ev.currentTarget.value);
let chat_groups = this.state.chat_groups.map((gp) => ({
...gp,
visible: gp.group_name
.toLowerCase()
.includes(ev.currentTarget.value),
}));
console.log(
"Before",
chat_groups.map((gp) => gp.visible)
);
this.setState({ chat_groups: chat_groups });
}}
不,不要这样做var thatState = this.state
它只是一个对象,它很容易发生变异,你不会得到更新,因为反应状态变化从未发生过。
而不是这样做var { chat_groups } = this.state
然后进一步使用它并最后设置状态this.setState({ chat_groups: chat_groups })
也尽量避免突变意味着复制chat_groups
的值也
看起来你在尝试直接操作状态,这在 React 中是一个很大的禁忌。
onChange={(ev) => {
this.setState({
chat_groups: this.state.chat_groups.map((gp) => {
gp["visible"] = gp.group_name
.toLowerCase()
.includes(ev.currentTarget.value);
return gp;
})
});
}}
问题是你正在改变 state
。
当您执行 var thatState = this.state;
时,两个对象的引用仍然相同。因此,当您更新 thatState.chat_groups
时,您也会自动成为 updating/mutating state
。
将您的 onChange
方法更改为喜欢以下内容
onChange = ev => {
console.log(ev.currentTarget.value);
let { chat_groups } = this.state;
chat_groups = chat_groups.map(gp => ({
...gp,
visible: gp.group_name.toLowerCase().includes(ev.currentTarget.value)
}));
this.setState(state => ({
...state,
chat_groups
}));
};
//Other code
//....
//....
<input
className="chat-group__search__input"
placeholder="Search for group..."
onChange={this.onChange} />
我怀疑在使用输入值检查 group_name
时存在一个问题,即您正在使用 gp.group_name.toLowerCase()
将 group_name
转换为 lower case
,但输入值您未转换为 lower case
。这可能是 visible
属性值未更新的原因之一。因此,在下面的代码片段中,我在比较时也将输入值转换为 lower case
。
在这里,下面是符合您要求的可运行代码段。在 setState
的回调函数中执行 console.log
并且状态正在更新。
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
currUserId: "--id--",
chats: [],
chat_groups: [{
group_name: "Group One"
}, {
group_name: "Group Two"
}],
users: []
}
}
onChange = ev => {
console.log(ev.currentTarget.value);
let {
chat_groups
} = this.state;
chat_groups = chat_groups.map(gp => ({
...gp,
visible: gp.group_name.toLowerCase().includes(ev.currentTarget.value.toLowerCase())
}));
this.setState(state => ({
...state,
chat_groups
}), () => { console.log(this.state.chat_groups); });
};
render() {
return <input
placeholder="Search for group..."
onChange={this.onChange} />
}
}
ReactDOM.render(<App />, document.getElementById("react"));
.as-console-wrapper {
max-height: 100% !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="react"></div>
只能使用 setState
方法更新状态。
您正在直接在上面的代码中改变状态 - this isn't recommended。你会得到意想不到的结果,这是不可预测的。
您应该这样做 - 创建一个新的更新对象并将其传递给 setState
。
onChange={(ev) => {
console.log(ev.currentTarget.value);
const updatedChatGroups = this.state.chat_groups.map((gp) => {
const visible = gp.group_name.toLowerCase().includes(ev.currentTarget.value);
return {
...gp,
visible,
};
});
// Update the modified object using this.setState().
this.setState({ chat_groups: updatedChatGroups });
}}
我正在尝试构建一个具有输入字段功能的聊天应用程序,它可以用作 chat_groups 数组的过滤器,该数组处于 chat_groups。这是我的代码的样子:
constructor(props) {
super(props);
this.state = {
currUserId: "--id--",
chats: [],
chat_groups: [],
users: [],
};
}
.
.
.
<input
className="chat-group__search__input"
placeholder="Search for group..."
onChange={(ev) => {
console.log(ev.currentTarget.value);
var thatState = this.state;
thatState.chat_groups = thatState.chat_groups.map(
(gp) => {
gp["visible"] = gp.group_name
.toLowerCase()
.includes(ev.currentTarget.value);
return gp;
}
);
// getting correct state in thatState variable
this.setState(thatState);
}}
/>
// getting old state in setState callback and componentDidUpdate lifecycle
奇怪的问题是我在设置状态之前在那个状态变量中得到了正确的值。但是在调用 setState 函数后,如果我尝试检查 setState 回调或 componentDidUpdate 生命周期中的状态,我只会得到旧状态。
我也为按键和更改事件尝试过。所以,似乎也不是事件的问题。
我想知道代码中是否存在明显的问题,或者我可以采取哪些措施来调试该问题。
编辑: 更改后,我当前的 onChange 如下所示,但问题仍然存在; setState 函数似乎没有改变状态,因为我只能在 componentDidUpdate 生命周期和 setState 回调中看到旧状态。
onChange={(ev) => {
console.log(ev.currentTarget.value);
let chat_groups = this.state.chat_groups.map((gp) => ({
...gp,
visible: gp.group_name
.toLowerCase()
.includes(ev.currentTarget.value),
}));
console.log(
"Before",
chat_groups.map((gp) => gp.visible)
);
this.setState({ chat_groups: chat_groups });
}}
不,不要这样做var thatState = this.state
它只是一个对象,它很容易发生变异,你不会得到更新,因为反应状态变化从未发生过。
而不是这样做var { chat_groups } = this.state
然后进一步使用它并最后设置状态this.setState({ chat_groups: chat_groups })
也尽量避免突变意味着复制chat_groups
的值也
看起来你在尝试直接操作状态,这在 React 中是一个很大的禁忌。
onChange={(ev) => {
this.setState({
chat_groups: this.state.chat_groups.map((gp) => {
gp["visible"] = gp.group_name
.toLowerCase()
.includes(ev.currentTarget.value);
return gp;
})
});
}}
问题是你正在改变 state
。
当您执行 var thatState = this.state;
时,两个对象的引用仍然相同。因此,当您更新 thatState.chat_groups
时,您也会自动成为 updating/mutating state
。
将您的 onChange
方法更改为喜欢以下内容
onChange = ev => {
console.log(ev.currentTarget.value);
let { chat_groups } = this.state;
chat_groups = chat_groups.map(gp => ({
...gp,
visible: gp.group_name.toLowerCase().includes(ev.currentTarget.value)
}));
this.setState(state => ({
...state,
chat_groups
}));
};
//Other code
//....
//....
<input
className="chat-group__search__input"
placeholder="Search for group..."
onChange={this.onChange} />
我怀疑在使用输入值检查 group_name
时存在一个问题,即您正在使用 gp.group_name.toLowerCase()
将 group_name
转换为 lower case
,但输入值您未转换为 lower case
。这可能是 visible
属性值未更新的原因之一。因此,在下面的代码片段中,我在比较时也将输入值转换为 lower case
。
在这里,下面是符合您要求的可运行代码段。在 setState
的回调函数中执行 console.log
并且状态正在更新。
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
currUserId: "--id--",
chats: [],
chat_groups: [{
group_name: "Group One"
}, {
group_name: "Group Two"
}],
users: []
}
}
onChange = ev => {
console.log(ev.currentTarget.value);
let {
chat_groups
} = this.state;
chat_groups = chat_groups.map(gp => ({
...gp,
visible: gp.group_name.toLowerCase().includes(ev.currentTarget.value.toLowerCase())
}));
this.setState(state => ({
...state,
chat_groups
}), () => { console.log(this.state.chat_groups); });
};
render() {
return <input
placeholder="Search for group..."
onChange={this.onChange} />
}
}
ReactDOM.render(<App />, document.getElementById("react"));
.as-console-wrapper {
max-height: 100% !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="react"></div>
只能使用 setState
方法更新状态。
您正在直接在上面的代码中改变状态 - this isn't recommended。你会得到意想不到的结果,这是不可预测的。
您应该这样做 - 创建一个新的更新对象并将其传递给 setState
。
onChange={(ev) => {
console.log(ev.currentTarget.value);
const updatedChatGroups = this.state.chat_groups.map((gp) => {
const visible = gp.group_name.toLowerCase().includes(ev.currentTarget.value);
return {
...gp,
visible,
};
});
// Update the modified object using this.setState().
this.setState({ chat_groups: updatedChatGroups });
}}