My goal is to update the state of my parent component with only a portion of data from the initial Json
So basically if for example the case text
get triggered:
1- I return the desired text
and render it in my component (I succeeded in doing that)
2- I also want to take this specific data and store it in the parent state
3- I will later use this data to create a form
I tried many things, I finally managed to update the state of the parent by passing down a function to the stateless function MyFunction
, but I keep getting a warning because the setState
is being called inside the render
method of the parent Component
Warning: Cannot update during an existing state transition (such as within
render or another component's constructor).
const MyFunction = props => {
switch (props.type) {
case 'image':
return props.json.data[props.key]
break
case 'text':
props.changeParent(props.json.data[props.key])
return props.json.data[props.key]
break
default:
return "Empty text"
break
}
}
class UserComponent extends Component {
constructor(props){
super(props)
this.state = {
active: false
}
}
render(){
return(
<div>
{ MyFunction({ type: 'text', key: 'first_name', ...this.props }) }
<img src={ MyFunction({ type: 'image', key: 'avatar', ...this.props }) } />
</div>
)
}
}
// Parent Component
class App extends Component {
constructor(props){
super(props)
this.state = {
json:[],
newJson: []
}
}
// Fetching data from an api
componentDidMount(){
fetch("https://reqres.in/api/users/2")
.then(response => response.json())
.then(json => {
this.setState({json: json })
})
}
// Update the parent Json using the data sent from the 2nd child
changeParent(jsonToUpdate){
this.setState({
newJson :
jsonToUpdate
})
}
render() {
return (
<div>
<UserComponent {...this.state} changeParent={(jsonToUpdate) => this.changeParent(jsonToUpdate)}/>
</div>
);
}
}
export default App;
Just use componentDidMount
lifecycle method and maintain a state for the data returned by myFunction
to avoid that warning like this
class UserComponent extends Component {
constructor(props){
super(props)
this.state = {
active: false,
// this state stores the data returned by function
myFunctionReturnData: ""
}
}
componentDidMount(){
let myFunctionReturnData = MyFunction({ type: 'text', key: 'first_name', ...this.props });
// Call the function and set the state by returned value
this.setState({ myFunctionReturnData })
}
render(){
return(
<div>
// Will render returned value when state will be set
{ this.state.myFunctionReturnData }
<img src={ MyFunction({ type: 'image', key: 'avatar', ...this.props }) } />
</div>
)
}
}
Update::
If you are calling MyFunction
multiple times then you should avoid calling changeParent
inside MyFunction
because you are calling MyFunction
inside render and calling changeParent
inside render will put this in loop because you are updating parent state in changeParent
function. A better solution i can think of according to given code is this
const MyFunction = props => {
switch (props.type) {
case 'image':
return props.json.data[props.key]
break
case 'text':
// Remove changeParent from here
return props.json.data[props.key]
break
default:
return "Empty text"
break
}
}
And in componentDidMount use MyFunction
to call the changeParent
like
componentDidMount(){
let myFunctionReturnData = MyFunction({ type: 'text', key: 'first_name', ...this.props });
// Call the parent function
this.props.changeParent(myFunctionReturnData)
}
You do not need to maintain any state now.
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.