I am building a simple todo list. I have a form for adding a new todo list item and under it are listed all items in the todo list. When I add a new item through a form, I want to refresh the list of existing todo list items.
Items.jsx:
class Items extends React.Component {
constructor(props) {
super(props);
this.state = {
items: [],
loading: true
};
}
componentDidMount() {
axios.get('/api/v1/items')
.then(response => {
this.setState({ items: response.data, loading: false });
});
console.log('state.items: '+this.state.items);
}
componentDidUpdate() {
axios.get('/api/v1/items')
.then(response => {
this.setState({ items: response.data, loading: false });
});
console.log('componentDidUpdate: '+this.state.items);
}
render() {
return (
<ItemSE.Group>
{
this.state.items.map(item => {
return <Item key={item.id} data={item} />
})
}
</ItemSE.Group>
);
}
}
export default Items
App.jsx:
class App extends Component {
constructor () {
super();
this.state = {
item_msg: ''
}
this.handleInputChange = this.handleInputChange.bind(this);
}
handleSubmit(e){
e.preventDefault();
console.log(this.state.item_msg);
axios.post('/api/v1/items', {
item: this.state.item_msg
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
handleInputChange(e) {
this.setState({ item_msg: e.target.value });
console.log('item_msg: '+this.state.item_msg);
}
render() {
return (
<div className="App">
<MainHeaderr />
<Container>
<NewItemForm
send_form={this.handleSubmit.bind(this)}
onInputChange={this.handleInputChange}
typed={this.state.item_msg} />
<Items />
</Container>
</div>
);
}
}
export default App;
I added componentDidUpdate
to the Items.jsx
file - when I add a new todo list, this new todo will indeed display immediately to the list - that's cool. However, I don't really feel this is the best practice.
When I look to the JS console, I see there hundreds of componentDidUpdate:
.
Thus, what's the best way to refresh a list to todos?
Fast Refresh is a React Native feature that allows you to get near-instant feedback for changes in your React components. Fast Refresh is enabled by default, and you can toggle "Enable Fast Refresh" in the React Native developer menu. With Fast Refresh enabled, most edits should be visible within a second or two.
To update React component every second with JavaScript, we can use the setInterval function to update a state in the useEffect hook. const [time, setTime] = useState(Date. now()); useEffect(() => { const interval = setInterval(() => setTime(Date.
When a value in the state object changes, the component will re-render, meaning that the output will change according to the new value(s).
This is one of the most challenging part for the newcomers into ReactJS
.
You should not make stateful components at the every level.
Choose a common owner for the state. In your case Items
component can't change it's state by itself without data from the parent App
component, so there are no reasons to keep the state in this place.
Basically, you should keep items
array and isLoading
flag in the App
component and then simply pass it into the Items
as a prop.
Then, you may update your list by re-fetching data after adding new item on the backend or just add it into the list.
Also, you should update parent's App
state on every input changes.
There are two ways:
You can keep it in NewItemForm
state and then pass onSubmit into the parent event handler as a function prop.
Just make it uncontrollable and don't keep it in state at all and parent will take this param from event.target.value
. (As it is now).
In both cases it won't re-render your list every time.
Because of this you should omit the handleInputChange
from App
component.
For example: App.js
constructor(props) {
super(props);
// Initial state
this.state = {
items: [],
isLoading: false,
}
}
handleSubmit(e){
e.preventDefault();
const { value } = e.target;
this.setState({ isLoading: true });
axios.post('/api/v1/items', {
item: value
})
.then(response => {
// there are several ways - choose ONE of them
// 1. If server returns you the created item
// you can just add this item into the list
this.setState(prevState => {
return {
items: [...prevState.items, response.data],
isLoading: false,
}
});
// 2. But if there are any users who can make changing simultaneously with you
// (if not - just imagine it :) ) - it's better to make re-fetch data from server
axios.get('/api/v1/items')
.then(response => {
this.setState(prevState => ({ items: response.data, isLoading: false });
})
.catch(err => { console.log('Something bad is happened:', err) });
}
Finally, just pass data it into your Items
component.
render() {
const { items, isLoading } = this.state;
return (
...
<Items items={items} isLoading={isLoading} />
...
)
}
I advice you to read this article if you haven't read it yet - https://reactjs.org/docs/thinking-in-react.html.
Hope it helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With