Search code examples
reactjstypescriptreact-propsreact-select

ReactJS Props are not loaded in componentWillMount() and componentDidMount()


I have the following code for my React-Select integration and need to set the selectedOption field for once before first render.

import React from 'react';
import Select from 'react-select';
 
interface IOption{
    value:string,
    label:string
}

interface Props{
    data : IOption[],
    onSelected : (id:string) => void
}

export default class ReactSelect extends React.Component<Props> {
    constructor(props){
        super(props)
        console.log("data from constructor : ",this.props.data)
    }

    tempSelectedOption:IOption | undefined
    state = {
        selectedOption:this.tempSelectedOption,
    };  

    componentWillMount(){
        this.setState({ selectedOption : this.props.data[0]},()=>{console.log("component will mount meth:",this.state.selectedOption)})
        console.log("data from componentWillMount : ", this.props.data)
    }

    componentDidMount(){
        this.setState({ selectedOption : this.props.data[0]},()=>{console.log("component did mount meth:",this.state.selectedOption)})
        console.log("data from componentDidMount : ", this.props.data)
    }

    handleChange = selectedOption => {
        this.setState({ selectedOption });
        this.props.onSelected(selectedOption.value)
        console.log(`Option selected:`, selectedOption);
    };

    render() {
        const{ selectedOption } = this.state;
        console.log("props.data in render :",this.props.data)

        return (
            <Select
                value = {selectedOption}
                onChange = {this.handleChange}
                options = {this.props.data}
            />
        );
    }
}

And here some console outputs

data from constructor : Array [] 
data from componentWillMount : Array [] 
props.data in render :  Array [] 
data from constructor :   Array [] 
data from componentWillMount : Array [] 
props.data in render :  Array [] 
data from constructor :   Array [] 
data from componentWillMount :   Array [] 
props.data in render : Array [] 
data from componentDidMount : Array [] 
data from componentDidMount : Array [] 
data from componentDidMount : Array [] 
props.data in render :  Array [ {…} ] 
props.data in render :  Array [] 
props.data in render :  Array [ {…} ] 
props.data in render :  Array [ {…} ] 
props.data in render :  Array [ {…} ] 
props.data in render :  Array [ {…} ] 
props.data in render :  Array [ {…} ] 
props.data in render :  Array [ {…} ] 
props.data in render :  Array [ {…}, {…} ] 
props.data in render :  Array [ {…} ] 

Solution

  • First of all, I want to thank everyone who paid attention to the question.

    As I also commented to @GiovanniEsposito's answer, the situation is pretty much as follows,

    In parent component a sdk is involved and the problem is I want to render data[0] as default value but, props.data is loaded after componentWillMount componentDidMount. Actually the sdk service call is returned even after first render function calling, so when the props.data are updated an additional render method is required. Then props.data is become available just in render function, so I had to handle the problem in the render function.

    I modified render() as,

    state = {
        selectedOption:null,
        propsLoaded:false
    };  
    
    render() {
        if(this.state.propsLoaded == false && this.props.data[0] != undefined){
            this.setState({ 
                selectedOption : this.props.data[0],
                propsLoaded : true
            })
        }
           
        return (
            <Select
                value = {this.state.selectedOption}
                onChange = {this.handleChange}
                options = {this.props.data}
            />
        );
    }
    

    As a result I solved my problem but I have a warning which seems not serious for me by now. If I am doing something very wrong please warn me :)

    Warning: Cannot update during an existing state transition (such as within `render`). 
    Render methods should be a pure function of props and state.