简体   繁体   中英

React Component rendering but not mounting thus unable to setState

I have a functional component called FillForm which calls a list of objects that are to be rendered sequentially within the FormFiller function. These components are rendering and displaying properly however when trying to get them to change their internal state I get the error

Warning: Can't call setState on a component that is not yet mounted. This is a no-op, but it might indicate a bug in your application. Instead, assign to this.state directly or define a state = {}; class property with the desired state in the MultipleChoiceQuestion component.

This is the formfiller function:

const FillForm = props => {

return (
    <div className={classes.container} key={1}>
        <p>Form Filler</p>
        {formElements[currentPage].map((Element => (
            Element.render()
        )))}
        <Button variant="contained" disabled={backDisabled} onClick={handleBack}>BACK</Button>
        <SubmitButton />
    </div>
)

}

I have removed code that is irrelevant to the problem here but the formElements are all children of my BaseElement and the formElements object is a list of aforementioned class objects that need to be rendered sequentially.

import React from "react"
  class BaseEntry extends React.Component {
constructor(props) {
    super(props);
    this.key = 0
    this.type = ""
}
setID(id) {
    this.key = id;
}
setType(type) {
    this.type = type;
}

userResponse() {
    return (null);
}
//This should always be overridden
render() {
    return (
        <React.Fragment>
            <div></div>
        </React.Fragment>
    )
}} export default BaseEntry;

Below is the code that is giving me problems and giving the error when I try to select a different choice in the multiple choice question.

class MultipleChoiceQuestion extends BaseEntry {
    constructor(question_text, choices) {
        super();
        this.question_text = question_text //A string
        this.choices = choices // [[1, "Choice text"], [2, "Choice text two"]]
        this.response = 1
        this.handleChange = this.handleChange.bind(this) 
        this.state = {response: 1}     
    }

    userResponse() {
        return ({
            "id" : this.id,
            "response" : this.response,
            "type" : this.type
        })
    }

    componentDidMount() {
        console.log("mounted")
    }

    handleChange(e) {
        console.log(e.target.value)
        this.setState({response: e.target.value})
    }
    
    render() {
        return (
            <React.Fragment key={this.key}>
                <div>
                    <h2>{this.response}</h2>
                    <FormControl component="fieldset">
                        <RadioGroup aria-label={this.question_text} value={this.response} name={this.question_text} onChange={this.handleChange}>
                            {this.choices.map(((choice, index) => (
                                <FormControlLabel value={choice[0]} control={<Radio />} label={choice[1]} key={index}/>
                            )))}
                        </RadioGroup>
                    </FormControl>
                </div>
            </React.Fragment>
        );
    }
}

export default MultipleChoiceQuestion; 

Here is the codesandbox: [https://codesandbox.io/s/priceless-leavitt-yh5dp?file=/src/FillForm.js]

render() {
    return (
        <React.Fragment key={this.key}> {/* remove key form here as your component dosen't have it */}
            <div>
                <h2>{this.state.response}</h2> {/* here is the problem use `this.state.resopnse` instead of `this.response` */}
                <FormControl component="fieldset">
                    <RadioGroup aria-label={this.question_text} value={this.response} name={this.question_text} onChange={this.handleChange}>
                        {this.choices.map(((choice, index) => (
                            <FormControlLabel value={choice[0]} control={<Radio />} label={choice[1]} key={index}/>
                        )))}
                    </RadioGroup>
                </FormControl>
            </div>
        </React.Fragment>
    );
}

you are using this.response in the render function you should instead use this.state.response . and remove this.key form the fragment as your component doesn't have such.

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