React js从父事件中更新子状态
React js update child state from an event in the parent
我有一个向客户端提供数据的 WebSocket,我在反应中使用 D3 在图表中显示它(数据),所以我希望我的图表根据数据改变,但要改变图表组件的状态,我必须从定义了 onMessage 事件的父组件访问它,我的问题是图表没有更新:
父组件:
class App extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
};
}
handleData(data) {
let result = JSON.parse(data);
this.setState((state) => {
state.data.push(result.c.gas);
});
}
render() {
return (
<div>
<Websocket
url={`ws://${window.location.host}/ws/mqtt_app/1/`}
onMessage={this.handleData.bind(this)}
/>
<Chart data={this.state.data} />
</div>
);
}
}
子组件:
const Chart = (props) => {
const [data, setData] = useState(props.data);
const svgRef = useRef();
useEffect(() => {
// chart definition
}, [data]);
return (
<React.Fragment>
<svg ref={svgRef}>
<g className="x-axis"></g>
<g className="y-axis"></g>
</svg>
</React.Fragment>
);
};
export default Chart;
谢谢
问题就在这里
const [data, setData] = useState(props.data);
const svgRef = useRef();
useEffect(() => {
// chart definition
}, [data]);
在首次呈现 Chart
组件时,您使用父组件的数据创建本地数据。使用 useEffect
,您正在查看本地数据(不是来自父级的数据),但它永远不会改变,因为您从不在 Chart
组件内部调用 setData
。如果它确实有效,本地状态将是不可能的。
解决方案是直接使用来自父级的数据并将您的 // chart definition
直接放在 Chart
中,而不是 useEffect
const Chart = (props) => {
const svgRef = useRef();
// chart definition
return (
<React.Fragment>
<svg ref={svgRef}>
<g className="x-axis"></g>
<g className="y-axis"></g>
</svg>
</React.Fragment>
);
};
export default Chart;
感谢@Mario 的评论,我发现了问题,首先我从子组件中删除了状态,并使用了 useEffect 中的道具,然后正如@Mario 所说,我改变了
this.setState((state) => {
state.gas.push(result.c.gas);
});
和
this.setState((state) => ({ gas: [...state.gas, result.c.gas] }));
因为,状态甚至没有改变,我只是在我已经拥有的气体阵列中添加了一个元素,但是为了改变状态直接 属性 应该辞职。
您需要为状态变量分配一个新值。请试试这个
this.setState(state => ({ data: [...state.data, result.c.gas] }))
在你的例子中你改变了它的值
我有一个向客户端提供数据的 WebSocket,我在反应中使用 D3 在图表中显示它(数据),所以我希望我的图表根据数据改变,但要改变图表组件的状态,我必须从定义了 onMessage 事件的父组件访问它,我的问题是图表没有更新:
父组件:
class App extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
};
}
handleData(data) {
let result = JSON.parse(data);
this.setState((state) => {
state.data.push(result.c.gas);
});
}
render() {
return (
<div>
<Websocket
url={`ws://${window.location.host}/ws/mqtt_app/1/`}
onMessage={this.handleData.bind(this)}
/>
<Chart data={this.state.data} />
</div>
);
}
}
子组件:
const Chart = (props) => {
const [data, setData] = useState(props.data);
const svgRef = useRef();
useEffect(() => {
// chart definition
}, [data]);
return (
<React.Fragment>
<svg ref={svgRef}>
<g className="x-axis"></g>
<g className="y-axis"></g>
</svg>
</React.Fragment>
);
};
export default Chart;
谢谢
问题就在这里
const [data, setData] = useState(props.data);
const svgRef = useRef();
useEffect(() => {
// chart definition
}, [data]);
在首次呈现 Chart
组件时,您使用父组件的数据创建本地数据。使用 useEffect
,您正在查看本地数据(不是来自父级的数据),但它永远不会改变,因为您从不在 Chart
组件内部调用 setData
。如果它确实有效,本地状态将是不可能的。
解决方案是直接使用来自父级的数据并将您的 // chart definition
直接放在 Chart
中,而不是 useEffect
const Chart = (props) => {
const svgRef = useRef();
// chart definition
return (
<React.Fragment>
<svg ref={svgRef}>
<g className="x-axis"></g>
<g className="y-axis"></g>
</svg>
</React.Fragment>
);
};
export default Chart;
感谢@Mario 的评论,我发现了问题,首先我从子组件中删除了状态,并使用了 useEffect 中的道具,然后正如@Mario 所说,我改变了
this.setState((state) => {
state.gas.push(result.c.gas);
});
和
this.setState((state) => ({ gas: [...state.gas, result.c.gas] }));
因为,状态甚至没有改变,我只是在我已经拥有的气体阵列中添加了一个元素,但是为了改变状态直接 属性 应该辞职。
您需要为状态变量分配一个新值。请试试这个
this.setState(state => ({ data: [...state.data, result.c.gas] }))
在你的例子中你改变了它的值