This seems to be a common issue, but I've tried several configurations and am consistently getting the error message Warning: Can't call setState on a component that is not yet mounted
. I have used setState()
in similar ways in other components of my app without issue, so I'm not sure why my App
component thinks I'm trying to call setState()
in the constructor when it is very clearly outside of it.
This is my attempt to use the componentDidMount()
lifecycle method. There is clearly something I am fully missing about this, but I can't glean much reading the documentation for setState()
. Especially considering that I am using this exact, same syntax in other parts of my app without issue. At any rate, here's what I'm working with:
import react from 'react';
class App extends react.Component {
constructor() {
super();
this.state = {
tasks: [
{
content:"walk dog",
date:"7/17/21",
priority:"high"
},
{
content:"take out trash",
date:"7/17/21",
priority:"low"
},
],
};
}
componentDidMount() {
this.addTask = this.addTask.bind(this);
}
addTask(content, date, priority) {
let taskUpdate = this.state.tasks;
let task = {
content: content,
date: date,
priority: priority
};
taskUpdate.push(task);
this.setState({
tasks: taskUpdate
});
}
render() {
return (
<>
<Header />
<Sidebar taskList={this.state.tasks} groupList={this.state.groups}>
</Sidebar>
</>
)
}
}
export { App };
The gist of this is to update the state of my App
component so that I can pass as props and re-render the list of tasks within the Sidebar
component. Apologies in advance since this seems to have been asked a million times, but I am simply confounded.
EDIT
For clarification, the addTask
method is called within a form that is rendered as part of an "add this task to the list of tasks" modal, e.g.:
const AddModal = ({ closeBtn, show, children }) => {
class Form extends Component {
constructor(props) {
super(props);
this.state = {
content: '',
date: '',
highPriority: ''
};
this.handleContent = this.handleContent.bind(this);
this.handleDate = this.handleDate.bind(this);
this.handlePriority = this.handlePriority.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleContent(event) {
this.setState({content: event.target.value});
}
handleDate(event) {
this.setState({date: event.target.value});
}
handlePriority(event) {
this.setState({highPriority: event.target.checked});
}
handleSubmit(event) {
event.preventDefault();
console.log("content: " + this.state.content + "\n" +
"date: " + this.state.date + "\n" +
"high priority: " + this.state.highPriority);
new App().addTask(this.state.content, this.state.date, this.state.highPriority);
closeBtn();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<input
type="text"
value={this.state.content}
onChange={this.handleContent}
placeholder="add a task (max 30 chars)"
maxLength="30"></input>
<input
type="date"
onChange={this.handleDate}></input>
<div className="checkbox-container">
<input
type="checkbox"
name="priority-checkbox"
onChange={this.handlePriority}></input>
<label
htmlFor="priority-checkbox">
high priority?
</label>
<button
type="submit"
id="add-task-submit">
+
</button>
</div>
</form>
);
}
};
const modalClassName = show ? "add-task-modal display-block" : "add-task-modal display-none";
return (
<div className={modalClassName}>
<div className="add-task-modal-content">
{children}
<button type="button" id="close-btn" onClick={closeBtn}>
x
</button>
<Form></Form>
</div>
</div>
);
};
The modal containing this form is rendered in a file that simply displays a list of tasks. The addTask()
method is successful in passing form data to 'App.js' as I can change the state directly, e.g. this.state.tasks = [...]
, but from what I have read this is extremely not best practice, and I need to use setState()
instead.
EDIT 2
So what started as me stumbling over a simple issue of altering state turned into a succinct and useful overview of react as a framework. Big thanks to user Robin Zigmond for the write-up and to Alexander Staroselsky for expounding even further with the suggestion of using the redux library. Your input helped immensely, and the components of my app are now correctly communicating with one another.
Suffice it to say my initial bug was not really an issue with setState
, this has been instrumental in helping me understand react on a broader level. Thanks again to everyone who contributed.