Невозможно изменить значения состояния с помощью setState () - PullRequest
0 голосов
/ 13 июля 2020

Я пытаюсь получить значения из компонента формы, используя реквизиты в основном компоненте приложения, где находится мое состояние. Используя значения, которые я получаю от реквизита, я хочу обновить основное состояние. Это мой код:

класс Приложение расширяет компонент {state = {dataset: "", cc: "", cw: 0, ch: 0, bw: 0, bh: 0, xspacing: 0 , yspacing: 0, barcolor: "",};

  // Function to use the data got from form component and setState
  dataForm = (
    dataset,
    canvascolor,
    canvaswidth,
    canvasheight,
    barwidth,
    barheight,
    xspacing,
    yspacing,
    barcolor
  ) => {
    this.setState({
      dataset,
      canvascolor,
      canvaswidth,
      canvasheight,
      barwidth,
      barheight,
      xspacing,
      yspacing,
      barcolor,
    });
    console.log(this.state);
  };

  render() {
    return (
      <div className="App">
        {/* This is the Form Component from where i'm getting my Data */}
        <DataForm dataForm={this.dataForm} />

        <DataGraph graph={this.state} />
      </div>
    );
  }
}

Я пытаюсь отправить свое обновленное состояние компоненту DataGraph, используя реквизиты, но это не работает. Это код моего компонента DataGraph ниже:

class DataGraph extends Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }

  drawChart() {
    const d = this.props.graph.dataset.split`,`.map((x) => +x);
    const accessToRef = d3
      .select(this.myRef.current)
      .append("svg")
      .attr("width", this.props.graph.cw)
      .attr("height", this.props.graph.ch)
      .style("background-color", this.props.graph.cc);

    accessToRef
      .selectAll("rect")
      .data(d)
      .enter()
      .append("rect")
      .attr("x", (d, i) => i * this.props.graph.xspacing)
      .attr("y", (d, i) => this.props.graph.ch - this.props.graph.yspacing * d)
      .attr("width", this.props.graph.bw)
      .attr("height", (d, i) => d * this.props.graph.bh)
      .attr("fill", this.props.graph.barcolor);
  }

  componentDidMount() {
    this.drawChart();
  }

  render() {
    return (
      <>
        <div
          style={{
            display: "flex",
            justifyContent: "center",
            alignItems: "center",
          }}
          ref={this.myRef}
          className="pb-5"
        ></div>
      </>
    );
  }
}

DataGraph.propTypes = {
  graph: PropTypes.object.isRequired,
};

setState() не устанавливает значения состояния. Пожалуйста, помогите.

Ответы [ 3 ]

1 голос
/ 13 июля 2020

состояние меняется, проблема заключается в том, что setState является задачей asyn c, поэтому вам нужно дождаться ее завершения и проверить, что ваше состояние обновляется, попробуйте следующий код: -

dataForm = (
dataset,
canvascolor,
canvaswidth,
canvasheight,
barwidth,
barheight,
xspacing,
yspacing,
barcolor
) => {
this.setState({
  dataset,
  canvascolor,
  canvaswidth,
  canvasheight,
  barwidth,
  barheight,
  xspacing,
  yspacing,
  barcolor,
},()=>{
  console.log(this.state);
});

};

setState возвращает обратный вызов после завершения sh своей задачи, вы можете использовать его для синхронизации c функции setState

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

const ExampleComponent =(props) =>{
  return <div>
             <Text>{{props.text}}</Text>
         </div>
}

, и передайте реквизиты в таком компоненте

<ExampleComponent text={this.state.text} />

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

0 голосов
/ 13 июля 2020

Решение заключается в использовании метода getDerivedStateFromProps() Stati c для получения состояния от родительского компонента в качестве свойств и использования этих свойств для инициализации состояния дочернего компонента. Вот код:

Передача состояния родительского компонента в качестве свойства дочернему компоненту:

<DataGraph graph={this.state} />

Использование вышеупомянутого метода для обновления состояния дочернего компонента:

class DataGraph extends Component {
  constructor() {
    super();
    this.state = {
      dataset: "",
      cc: "",
      cw: 0,
      ch: 0,
      bw: 0,
      bh: 0,
      xspacing: 0,
      yspacing: 0,
      barcolor: "",
    };
    this.myRef = React.createRef();
  }

  static getDerivedStateFromProps(props, state) {
    return {
      dataset: props.graph.dataset,
      cc: props.graph.cc,
      cw: props.graph.cw,
      ch: props.graph.ch,
      bw: props.graph.bw,
      bh: props.graph.bh,
      xspacing: props.graph.xspacing,
      yspacing: props.graph.yspacing,
      barcolor: props.graph.barcolor,
    };
  }

  drawChart() {
    const d = this.state.dataset.split`,`.map((x) => +x);
    const accessToRef = d3
      .select(this.myRef.current)
      .append("svg")
      .attr("width", this.state.cw)
      .attr("height", this.state.ch)
      .style("background-color", this.state.cc);

    accessToRef
      .selectAll("rect")
      .data(d)
      .enter()
      .append("rect")
      .attr("x", (d, i) => i * this.state.xspacing)
      .attr("y", (d, i) => this.state.ch - this.state.yspacing * d)
      .attr("width", this.state.bw)
      .attr("height", (d, i) => d * this.state.bh)
      .attr("fill", this.state.barcolor);
  }

  render() {
    this.drawChart();
    return (
      <>
        <div
          style={{
            display: "flex",
            justifyContent: "center",
            alignItems: "center",
          }}
          ref={this.myRef}
          className="pb-5"
        ></div>
      </>
    );
  }
}
Метод getDerivedStateFromProps() - это метод Stati c, как упоминалось выше, поэтому имейте это в виду при его использовании. Также не инициализируйте "props" в constructor() или super(), иначе это не сработает. Слава богу, сработало, ненавижу Redux Boilerplate ?.
0 голосов
/ 13 июля 2020

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

для решения этой проблемы у вас есть чтобы использовать крючок жизненного цикла реакции под названием componentWillReceiveProps

вот так

  componentWillReceiveProps() {
    this.drawChart();
  }

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

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