Reputation: 471
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
)
)
}
Upvotes: 0
Views: 1751
Reputation: 42170
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;
}
}
Upvotes: 1
Reputation: 2970
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 };
}
}
Upvotes: 2
Reputation: 798
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]})
Upvotes: 0