React js从父事件中更新事件的子状态

时间:2020-06-16 21:57:35

标签: javascript reactjs websocket react-d3

我有一个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;

谢谢

3 个答案:

答案 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] }))

在您的情况下,您正在改变其值