简体   繁体   中英

setstate is not rerendering child components when called from componentDidMount

I have a Parent component from which I am setting

interface SignUpPropModel {}
interface SignUpState{
    form:(InputProps&{desc: string})[];
}
export class SignUp extends Component<SignUpPropModel, SignUpState > {
    state: SignUpState = {
        form:[]
    }
    constructor(props:SignUpPropModel){
        super(props)
        this.state.form = [{
                type:"text",
                classnames:"form-control",
                id: "username",
                name: "username",
                isvalid: false,
                placeholder:"Username",
                value:'',
                desc:'Username'
            }]            
    }
    componentDidMount() {
            let form = [...this.state.form];
            if(form){
                form[0].isvalid=false;
                this.setState({form: form});
            }  
    }
    render(){
        return (
                    <form className='my-3'>
                        {this.state.form?.map((inputProps) => ( 
                                    <div key={inputProps.id} className="form-group mx-3" >
                                        <label htmlFor={inputProps.id}>{inputProps.desc}</label>
                                        <Input  {...inputProps}/>
                                    </div>)) }
                    </form>
        );
    }
}

Input Component -

interface IProps{
    type:'text'|'checkbox'|'radio'|'password';
    value?: any;
    name?: string;
    id?:string;
    onClick?: ((event: React.MouseEvent<HTMLInputElement, MouseEvent>) => void);
    onChange?:((event: React.ChangeEvent<HTMLInputElement>) => void);
    classnames: string;
    placeholder?: any;
}
export interface InputProps extends IProps{
    isvalid?: boolean;
}
interface InputState{
    isvalid: boolean|undefined;
}
export class Input extends Component<InputProps, InputState>{
    iProps: IProps|null = null;
    state: InputState= {
        isvalid: true
    }
    constructor(props: InputProps){
        super(props);
        ({isvalid: this.state.isvalid, ...this.iProps} = this.props);
        this.state.isvalid = this.state.isvalid===undefined ? true: this.props.isvalid;          
    }
    render(){
        return (
                <input className={ this.state.isvalid===true ? this.iProps?.classnames : 'is-invalid' + ' ' + this.props.classnames} {...this.iProps}   />
        )
    }
}

Input is a child component. It renders the first time. In the componentDidMount os parent component, I am changing the state of the parent component using setState . I verified that the state of the parent component is changed but somehow render is not triggered by React. Thus, the change of state is not getting reflected in the child component.

Kindly help me to find what's wrong with my code.

I got my answer to this issue.

I was assuming that whenever React executes render , it recreates the component. ie I was assuming that rerendering will trigger the constructor of Input component. Finally, I did some debugging in the application and found that constructor won't be executed while re-rendering. Thus, I was not getting updated value in the state of Input .

Found out that I have to use a lifecycle method named componentDidUpdate in Input .

 componentDidUpdate(){
        const isvalid = this.props.isvalid===undefined ? true: this.props.isvalid;
        if(this.state.isvalid !== isvalid)
            this.setState({isvalid: isvalid});
    }

I added this in Input and the issue is resolved.

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