我正在构建一个简单的待办事项列表。我有一个用于添加新的待办事项列表项的表单,在它下面列出了待办事项列表中的所有项目。当我通过表单添加新项目时,我想刷新现有待办事项列表。
项目.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
应用程序.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;
我将 componentDidUpdate 添加到 Items.jsx 文件中 - 当我添加一个新的待办事项列表时,这个新的待办事项确实会立即显示到列表中 - 这很酷。但是,我真的不觉得这是最佳做法。
当我查看 JS 控制台时,我看到那里有数百个 componentDidUpdate:。
因此,将列表刷新为待办事项的最佳方式是什么?
最佳答案
对于 ReactJS 的新手来说,这是最具挑战性的部分之一。
你不应该在每一层都制作有状态的组件。
为状态选择一个共同的所有者。在您的情况下,如果没有来自父 App 组件的数据,Items 组件无法自行更改其状态,因此没有理由将状态保留在此处。
基本上,您应该在 App 组件中保留 items 数组和 isLoading 标志,然后将其简单地传递到 Items 作为 Prop 。
然后,您可以通过在后端添加新项目后重新获取数据或直接将其添加到列表中来更新您的列表。
此外,您应该在每次输入更改时更新父级的 App 状态。
有两种方式:
您可以将其保持在 NewItemForm 状态,然后将 onSubmit 作为函数属性传递给父事件处理程序。
只是让它无法控制并且根本不保持状态,父级将从 event.target.value 中获取此参数。 (就像现在一样)。
在这两种情况下,它不会每次都重新呈现您的列表。
因此,您应该从 App 组件中省略 handleInputChange。
例如: 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) });
}
最后,只需将数据传递到您的 Items 组件即可。
render() {
const { items, isLoading } = this.state;
return (
...
<Items items={items} isLoading={isLoading} />
...
)
}
如果您还没有阅读这篇文章,我建议您阅读它 - https://reactjs.org/docs/thinking-in-react.html .
希望对您有所帮助。
关于javascript - React - 在添加新元素后刷新数据列表的最佳做法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49378949/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
当我使用Bundler时,是否需要在我的Gemfile中将其列为依赖项?毕竟,我的代码中有些地方需要它。例如,当我进行Bundler设置时:require"bundler/setup" 最佳答案 没有。您可以尝试,但首先您必须用鞋带将自己抬离地面。 关于ruby-我需要将Bundler本身添加到Gemfile中吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/4758609/
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返
我有一个ModularSinatra应用程序,我正在尝试将Bootstrap添加到应用程序中。get'/bootstrap/application.css'doless:"bootstrap/bootstrap"end我在views/bootstrap中有所有less文件,包括bootstrap.less。我收到这个错误:Less::ParseErrorat/bootstrap/application.css'reset.less'wasn'tfound.Bootstrap.less的第一行是://CSSReset@import"reset.less";我尝试了所有不同的路径格式,但它
我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以
是否有类似“RVMuse1”或“RVMuselist[0]”之类的内容而不是键入整个版本号。在任何时候,我们都会看到一个可能包含5个或更多ruby的列表,我们可以轻松地键入一个数字而不是X.X.X。这也有助于rvmgemset。 最佳答案 这在RVM2.0中是可能的=>https://docs.google.com/document/d/1xW9GeEpLOWPcddDg_hOPvK4oeLxJmU3Q5FiCNT7nTAc/edit?usp=sharing-知道链接的任何人都可以发表评论
它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput