简体   繁体   中英

How to store all array values into a single React state?

I have a config file which contains an array that gets data from redux

"datapath": [
  "common.registration.rgsnInfoRs[0].value",  // street name
  "common.registration.rgsnInfoRs[1].value",  // city
  "common.registration.rgsnInfoRs[2].value",  // state
  "common.registration.rgsnInfoRs[3].value"   // zip code
]

In my react component, when I tried to render the data from this array it only returns back the data for the zip code. How can I make my component render all of index data in my render method?

constructor(props) {
  super(props);
  this.state = {
    // data: '',
    data: []
  }
}
componentDidMount(){
  if(_.get(this.props, 'datapath')){
    _.map(this.props.datapath, (item, i) => {
      let data=_.get(this.props.state,`i`);
      this.setState({data})
    })
  }
}

// static getDerivedStateFromProps(props, state) {
//   if(_.get(props, 'datapath')){
//     _.map(props.datapath, (item, i) => {
//       let data=_.get(props.state,item);
//       state.data = data;
//     }) 
//   }
// }


static getDerivedStateFromProps(props, state) {
    if(_.get(props, 'datapath')){
      _.map(props.datapath, (item, i) => {
        let data=_.get(props.state,item);
        this.setState((prevState) => {
          return { data: [...prevState.data, data] }
         });
      })
    }
  }

render() {
  const {type, label} = this.props;
  return (
    type === "grid" ? (
      <Grid.Column style={style}>
        <strong>{label ? `${label}:` : null}</strong> {this.state.data}
      </Grid.Column>
    ) : (
      null
    )
  )
}

Your initial data type for this.state.data is an array. But in the following line, it gets the value of the item (in this case, it's either street name, city, state or zipcode). These values are string type and override the this.state.data datatype from array to string.

let data=_.get(props.state, `i`); // This is incorrect

You should append the value in the state data instead of assign in componentDidMount

componentDidMount() {
  if(_.get(this.props, 'datapath')){
    _.map(this.props.datapath, (item, i) => {
       let data=_.get(this.props.state,`i`);
       this.setState((prevState) => {
          return { data: [...prevState.data, data] }
        });
    })
  }
}

Now Let's look at getDerivedStateFromProps function. This is a static function and you can not use this inside a static function. According to the react docs , this function returns the updated state.

static getDerivedStateFromProps(props, state) {
const newData = [];
if(_.get(props, 'datapath')) {
  _.map(props.datapath, (item, i) => {
    let data=_.get(props.state,item);
    newData.push(data);
  });
  return { data: newData };
}

}

I think that you are not asking the right questions. It is generally a bad idea to store data from props in state because it can lead to stale and outdated data. If you can already access it from props, then you don't need to also have it in state.

Your component receive a prop state which is an object and a prop datapath which is an array of paths used to access properties on that state . This is already weird and you should look into better patterns for accessing redux data through selector functions.

But if we can't change that, we can at least change this component. You can convert an array of paths to an array of values with one line of code:

const data = this.props.datapath.map( path => _.get(this.props.state, path) );

All of the state and lifecycle in your component is unnecessary. It could be reduced to this:

class MyComponent extends React.Component {
  render() {
    const { type, label = "", state, datapath = [] } = this.props;
    const data = datapath.map((path) => _.get(state, path, ''));
    return type === "grid" ? (
      <Grid.Column style={style}>
        <strong>{label}</strong> {data.join(", ")}
      </Grid.Column>
    ) : null;
  }
}

I think, when you are looping through the data and setting the state you are overriding the old data present in the state already.

may be you will have to include the previous data as well as set new data in it something like this.

this.setState({data : [...this.state.data, data]})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM