我有一个WebSocket,它将数据馈送到客户端,并且我在React中使用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;
谢谢
答案 0 :(得分:0)
问题在这里
const [data, setData] = useState(props.data);
const svgRef = useRef();
useEffect(() => {
// chart definition
}, [data]);
在第一次渲染Chart
组件时,您将使用父组件中的数据创建本地数据。使用useEffect
时,您正在观看的是本地数据(不是来自父级的数据),但是它永远不会改变,因为您永远不会在setData
组件内部调用Chart
。如果它能奏效,就不可能有地方政府。
解决方案是直接使用来自父级的数据,并将您的// 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;
答案 1 :(得分:0)
感谢@Mario在评论中发现了问题,首先我从子组件中删除了状态,并在useEffect中使用了道具,然后,如@Mario所说,我更改了
this.setState((state) => {
state.gas.push(result.c.gas);
});
使用
this.setState((state) => ({ gas: [...state.gas, result.c.gas] }));
因为状态甚至都没有改变,所以我只向我已经拥有的气体数组添加了一个元素,但是要改变状态,应该直接赋值直接的属性。
答案 2 :(得分:0)
您需要为状态变量分配一个新值。请尝试这个
this.setState(state => ({ data: [...state.data, result.c.gas] }))
在您的情况下,您正在改变其值