React js обновить дочернее состояние из события в родительском - PullRequest
0 голосов
/ 17 июня 2020

У меня есть 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;

Спасибо

Ответы [ 3 ]

0 голосов
/ 17 июня 2020

благодаря @Mario в комментариях я обнаружил проблему, сначала я удалил состояние из дочернего компонента и использовал props в useEffect, а после этого, как сказал @Mario, я изменил

     this.setState((state) => {
        state.gas.push(result.c.gas);
      });

с

this.setState((state) => ({ gas: [...state.gas, result.c.gas] }));

, потому что состояние даже не изменилось, я только добавил элемент в массив газа, который у меня уже был, но для изменения состояния необходимо отказаться от прямого свойства.

0 голосов
/ 17 июня 2020

Вам необходимо присвоить новое значение переменной состояния. Пожалуйста, попробуйте это

this.setState(state => ({ data: [...state.data, result.c.gas] }))

В вашем случае вы изменили его значение

0 голосов
/ 17 июня 2020

Проблема здесь

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;
...