小道具を状態変数に割り当てようとするReactが機能しない

Aug 25 2020

親コンポーネントから取得した小道具を割り当てて、子コンポーネントの状態に割り当てようとしています(最初に状態に割り当てた小道具データを操作したいため)。

状態変数をログに記録すると、空の配列として出力されますが、レンダーで新しい変数を作成し、それに小道具を割り当ててログに記録します。それは私が必要とするデータを示しています。また、ログthis.propsを記録するだけで、小道具が必要なデータを保持していることがはっきりとわかります。

数回前に小道具を割り当てて状態を示したので、今回は何がそれほど違うのかわかりません。

小道具を子に渡す親コンポーネント:

  <ShowAvailableTimeslots onClick={this.getSelectedTimeslot} allTimeSlots={this.state.AvailabletimeSlots} /> 

小道具を状態に割り当てようとする子コンポーネント:

class ShowAvailableTimeslots extends Component {
    constructor(props) {
      super(props)
        this.state = {
            sliceEnd: 5,
            sliceStart:0,
            selectedSlotValue: "",
            timeSlotArr: this.props.allTimeSlots,
            // timeSlotSlice: timeSlotArr.slice(this.state.sliceStart, this.state.sliceEnd)
        }
      
    }

    handleTimeSlotClick = (timeSlot) => {
        this.setState({ selectedSlotValue: timeSlot }, () => {
            this.props.onClick(this.state.selectedSlotValue)
            console.log('time slot value', timeSlot)
          
        });
    }
    previousSlots =()=>{
        var test;
    }
    forwordSlots =()=>{
        var test;
    }    

    
    render() {
         var timeSlotArrRender = this.props.allTimeSlots; 
        return (
            <React.Fragment>

                {console.log("state", this.state.timeSlotArr)} // --> doesn't show data
                {console.log("props", this.props)} // --> does show data
                {console.log("render variable", timeSlotArrRender )} // --> does show data


                <button className="button btn" onClick={() => this.previousSlots()} disabled={this.state.sliceStart === 0}>left</button>
                {/* {this.state.timeSlotArr.map(timeSlot => <a className="timeslot btn " key={timeSlot} value={timeSlot} onClick={() => this.handleTimeSlotClick(timeSlot)}>{timeSlot}</a>)
                } */}
                <button className="button btn">right</button>

            </React.Fragment>
        )
    }
}

export default ShowAvailableTimeslots

回答

1 Anup Aug 25 2020 at 00:01

コンストラクターは、コンポーネントのライフサイクルが始まるときに呼び出されます。親からthis.state.AvailabletimeSlotsを渡しており、その時点でコンストラクターが既に呼び出されており、timeSlotArrの割り当てが既に行われているためです。

timeSlotArr: this.props.allTimeSlots // will not work

あなたはライフサイクルの方法やフックの助けを借りなければなりません

componentWillReceiveProps(nextProps){
   this.setState({timeSlotArr: nextProps.allTimeSlots })
} 

新しい変更に応じて、使用する必要があります

static getDerivedStateFromProps(nextProps, prevState){
   return {
      timeSlotArr: nextProps.allTimeSlots
  };
}
RahulMaddineni Aug 24 2020 at 23:17

私はそれがうまく機能しています。 https://jsfiddle.net/85zc4Lxb/

class App extends React.Component {
  render() {
    return (<Child passing="I am being passed to child" />);
  }
}

class Child extends React.Component {
  constructor(props) {
    super(props)
      this.state = {
        passedProp: this.props.passing,
      }
  }

  render() {
      return (
          <React.Fragment>
            <button>{this.state.passedProp}</button>
          </React.Fragment>
      )
  }
}

ReactDOM.render(
  <App />,
  document.getElementById('container')
);

Hamza Aug 24 2020 at 23:28

シナリオを再作成しようとしていますが、すべてのファイルをもう一度保存してから確認してください。

親コンポーネント

import React, { Component } from "react";
import TestOne from "./Components/TestOne/TestOne";

export class App extends Component {
  state = {
    x: "x data",
    y: "y data",
  };
  render() {
    return (
      <div>
        <TestOne x={this.state.x} allTimeSlots={this.state.y}/>
      </div>
    );
  }
}

export default App;

子コンポーネント

import React, { Component } from "react";

export class TestOne extends Component {
  constructor(props) {
    super(props);
    this.state = {
      sliceEnd: 5,
      sliceStart: 0,
      selectedSlotValue: "",
      timeSlotArr: this.props.x,
    };
  }
  render() {
    var timeSlotArrRender = this.props.allTimeSlots;
    return (
      <React.Fragment>
        {console.log("state", this.state.timeSlotArr)}
        {console.log("props", this.props)}
        {console.log("render variable", timeSlotArrRender)}

        <button className="button btn">right</button>
      </React.Fragment>
    );
  }
}

export default TestOne;

結果: