React-在其中添加新元素后刷新数据列表的最佳实践是什么? [英] React - What's the best practice to refresh a list of data after adding a new element there?
问题描述
我正在建立一个简单的待办事项清单.我有一个用于添加新的待办事项列表项的表单,在该表单下列出了待办事项列表中的所有项.通过表单添加新项目时,我想刷新现有待办事项列表项目的列表.
Items.jsx:
class Items扩展了React.Component {构造函数(道具){超级(道具);this.state = {项目: [],载入中: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);}使成为() {返回 (< ItemSE.Group>{this.state.items.map(item => {返回< Item key = {item.id} data = {item}/>})}</ItemSE.Group>);}}导出默认项目
App.jsx:
class App扩展了组件{构造函数(){极好的();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',{项目:this.state.item_msg}).then(function(response){console.log(response);}).catch(函数(错误){console.log(错误);});}handleInputChange(e){this.setState({item_msg:e.target.value});console.log('item_msg:'+ this.state.item_msg);}使成为() {返回 (< div className ="App">< MainHeaderr/><容器>< NewItemFormsend_form = {this.handleSubmit.bind(this)}onInputChange = {this.handleInputChange}typed = {this.state.item_msg}/><项目/></容器></div>);}}导出默认应用程序;
我在 Items.jsx
文件中添加了 componentDidUpdate
-当我添加新的待办事项列表时,这个新的待办事项确实会立即显示在列表中-太酷了.但是,我并不是真的认为这是最佳做法.当我查看JS控制台时,看到数百个 componentDidUpdate:
.
因此,刷新待办事项列表的最佳方法是什么?
对于刚进入 ReactJS
的新手来说,这是最具挑战性的部分之一.您不应该在每个级别上构成有状态的组件.
选择国家的共同所有者.在您的情况下,没有父 App
组件的数据, Items
组件无法自行更改其状态,因此没有理由将状态保持在该位置.>
基本上,应该将 items
数组和 isLoading
标志保留在 App
组件中,然后将其传递到 Items
作为道具.
然后,您可以通过在后端添加新项之后重新获取数据来更新列表,也可以只将其添加到列表中.
此外,您应该在每次输入更改时更新父级的 App
状态.
有两种方法:
-
您可以将其保持为
NewItemForm
状态,然后将onSubmit作为函数prop传递给父事件处理程序. -
仅使其变得不可控制并且根本不保持其状态,父级将从
event.target.value
中获取此参数.(现在).
在两种情况下,它都不会每次都重新呈现您的列表.因此,您应该从 App
组件中省略 handleInputChange
.
例如: App.js
constructor(props){超级(道具);//初始状态this.state = {项目: [],isLoading:否,}}handleSubmit(e){e.preventDefault();const {value} = e.target;this.setState({isLoading:true});axios.post('/api/v1/items',{项目:价值}).then(response => {//有几种方法-选择其中一种//1.如果服务器返回您创建的项目//您只需将此项目添加到列表中this.setState(prevState => {返回 {项目:[... prevState.items,response.data],isLoading:否,}});//2.但是如果有任何用户可以与您同时进行更改//(如果不是-只是想像一下:))-最好从服务器重新获取数据axios.get('/api/v1/items').then(response => {this.setState(prevState =>({项目:response.data,isLoading:false});}).catch(err => {console.log('发生了不好的事情:',err)});}
最后,只需将数据传递到您的 Items
组件中即可.
render(){const {items,isLoading} = this.state;返回 (...< Items items = {items} isLoading = {isLoading}/>...)}
如果您尚未阅读本文,我建议您阅读本文- https://reactjs.org/docs/thinking-in-react.html .
希望有帮助.
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?
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.
这篇关于React-在其中添加新元素后刷新数据列表的最佳实践是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!