我有一个上级组件:
Sub Concatenate()
' Concatenate two columns
Dim l As Long, lRow As Long
With ActiveSheet
lRow = .Range("A" & Rows.Count).End(xlUp).Row
For l = 2 To lRow
ActiveSheet.Cells(l, 3) = .Cells(l, 1) & " " & .Cells(l, 2)
Next l
End With
End Sub
...和一个子组件:
import React, { Component } from "react";
import { Button } from "./Button";
export class Dashboard extends Component {
constructor(props) {
super(props);
this.state = {
numbers: [],
disabled: false
};
this.setNum = this.setNum.bind(this);
}
setNum(num) {
if (!this.state.numbers.includes(num)) {
this.setState(prevState => ({
numbers: [...prevState.numbers, num]
}));
} else if (this.state.numbers.includes(num)) {
let nums = [...this.state.numbers];
let index = nums.indexOf(num);
nums.splice(index, 1);
this.setState({ numbers: nums });
console.log(this.state.numbers);
}
if (this.state.numbers.length >= 4) {
this.setState({ disabled: true });
} else if (this.state.numbers.length < 4) {
this.setState({ disabled: false });
}
}
render() {
return (
<div className="board-container">
<div className="board">
<div className="row">
<Button
id="1"
numbers={this.state.numbers}
onChange={this.setNum}
disabled={this.state.disabled}
/>
<Button
id="2"
numbers={this.state.numbers}
onChange={this.setNum}
disabled={this.state.disabled}
/>
<Button
id="3"
numbers={this.state.numbers}
onChange={this.setNum}
disabled={this.state.disabled}
/>
<Button
id="4"
numbers={this.state.numbers}
onChange={this.setNum}
disabled={this.state.disabled}
/>
</div>
</div>
</div>
);
}
}
每当单击任何Button组件时,Parent组件都会获取子Button的import React, { Component } from "react";
export class Button extends Component {
constructor(props) {
super(props);
this.state = {
isChecked: false
};
this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
this.setState({
isChecked: !this.state.isChecked
});
var num = e.target.value;
this.props.onChange(num);
}
render() {
const { isChecked } = this.state;
if (isChecked === true) {
var bgColor = "#f2355b";
} else {
bgColor = "#f7f7f7";
}
let disabled = this.props.disabled;
if (this.props.numbers.includes(this.props.id)) {
disabled = false;
}
return (
<div className="number-container" id="checkboxes">
<label
className={!isChecked && disabled === false ? "num" : "checked-num"}
style={{ backgroundColor: bgColor }}
>
{" "}
{this.props.id}
<input
type="checkbox"
name={this.props.id}
value={this.props.id}
id={this.props.id}
onChange={this.handleChange}
checked={isChecked}
disabled={disabled}
/>
</label>
</div>
);
}
}
值并将其放入其id
状态数组。每当取消选中一个Button时,通过删除子Button的numbers
,Parent更新处于numbers
状态。
如果我的代码正确,则预期的行为是每当单击id
复选框时,“父编号”状态将立即更新(添加或删除数字)。但是,它总是在更新时落后一步。
我知道,该问题正在处理无法立即更新的React状态,我已经检查了Stackoverflow上的类似问题。问题是我无法弄清楚如何使这两个组件以适当的方式相互交互。该问题的解决方案是什么?
答案 0 :(得分:2)
这是来自codeandbox的三个屏幕截图
如果要使用它,请找到链接https://codesandbox.io/s/w2q8ypnxjw
我所做的是,我基本上复制并粘贴了您的代码,并更新了setNum函数以反映Think-Twice建议的更改
setNum(num) {
if (!this.state.numbers.includes(num)) {
this.setState(
prevState => ({
numbers: [...prevState.numbers, num]
}),
() => {
console.log("state logged inside if", this.state.numbers);
}
);
} else if (this.state.numbers.includes(num)) {
let nums = [...this.state.numbers];
let index = nums.indexOf(num);
nums.splice(index, 1);
this.setState({ numbers: nums }, () => {
console.log("state logged inside else if", this.state.numbers);
});
}
if (this.state.numbers.length >= 4) {
this.setState({ disabled: true });
} else if (this.state.numbers.length < 4) {
this.setState({ disabled: false });
}
}
因此,在进一步介绍之前,让我们快速解决与React和setState有关的几件事
如B12Toaster所述,并提供了一个包含 官方文件中的报价
setState()并不总是立即更新组件。它可能 批量更新或将更新推迟到以后。
Think-Twice也指出了
基本上setState在React中是异步的。修改值时 使用setState您将只能在以下位置查看更新的值 渲染。
因此,如果您想查看某个地方的即时状态变化,
您触发setState时,可以将回调函数用作
这样的setState(updater[, callback])
使用setState和updater时有两种方法, 您可以传递一个对象,也可以传递一个函数 以两次思考为例,对象作为更新程序传递
this.setState({ numbers: nums } //updater, () => {
console.log(this.state.numbers); //this will print the updated value here
});
将一个函数用作更新程序时(在setNum函数中, 已经做到了),则可以像下面那样利用回调函数
if (!this.state.numbers.includes(num)) {
this.setState(
prevState => ({
numbers: [...prevState.numbers, num]
}),
() => {
console.log("state logged inside if", this.state.numbers);
}
);
}
您当前的实现和通信结构看起来还不错。它实际上称为Lifting State Up,官方文档也建议使用此名称。 基本上,您将数组编号的状态存储在父组件中(可以将其视为事实的来源),然后将更改状态的方法作为对其子组件的支持。
在我提供的codesandbox链接中,功能按我期望的方式运行(至少这是我对您的代码的期望)
答案 1 :(得分:1)
基本上setState在React中是异步的。使用setState修改值时,您将只能在render中看到更新后的值。但是要立即查看更新的状态值,您需要执行以下操作
this.setState({ numbers: nums }, () => {
console.log(this.state.numbers); //this will print the updated value here
});