原始问题

我正在尝试使用React渲染项目列表。 关键是项目共享一个公共状态,可以由每个项目控制。

为了简单起见,假设我们有一个字符串数组。 我们有一个 List组件,该组件映射到数组上并生成 Item组件。 每个 Item都有一个按钮,单击该按钮可以更改列表中所有项目的状态(我提供了一个代码段来传达我要执行的操作)。

我将 state存储在 List组件中,并将其值通过 props传递给每个 ItemItem 我遇到的问题是,单击按钮(在 Item内)根本没有更改UI状态。 我认为问题与以下事实有关:单击按钮后 items不会更改(正确地如此),因此React不会重新呈现列表(鉴于道具本身,我希望进行某种UI更新当 List状态更改时,传递给 Item isEditing也会更改)。

我如何让React处理这种情况?

注意:单击代码片段中的“ Edit按钮时似乎出现脚本错误,但是在本地运行时不会遇到该错误。 相反,不会引发任何错误,但是UI中的任何内容都不会更新。 调试它时,可以看到 List中的状态更改没有传播到其子级。

编辑的问题

鉴于最初的问题还不够清楚,我在下面重新表述。

目标

我想在React渲染项目列表。 每个项目应显示一个单词和一个“ Edit按钮。 用户一次只能编辑一个项目。

验收标准

  • 加载后,用户会看到单词列表,每个单词旁边都有一个“ Edit按钮。
  • 单击项目1的“ Edit ”时,只有项目1变为可编辑,“ Edit按钮变为“ Save按钮。 列表中的其余项目将不再显示其相应的“ Edit按钮。
  • 单击项目0的Save ,将显示该项目的新值。 所有“编辑”按钮(对于其余项目)应再次变为可见。

问题

在我最初的实现中,我将编辑状态存储在父组件( List )中,但是这种状态没有正确地传播到其ItemItem

注意:状态管理逻辑缺少我的原始实现,后来我发现这是主要的罪魁祸首(请参阅下面的响应)。 它也有一个绑定错误,如下面的@Zhang所述。 我将其留在此处以供将来参考,尽管这并不是一个很好的例子。

这是我的原始实现:

 const items = ['foo', 'bar']; class List extends React.Component { constructor(props) { super(props); this.state = { isEditing: false }; } toggleIsEditing() { this.setState((prevState) => { return { isEditing: !prevState.isEditing } }); } render() { return ( <ul> {items.map((val) => ( <Item value={val} toggleIsEditing={this.toggleIsEditing} isEditing={this.state.isEditing}/> ))} </ul> ); } } class Item extends React.Component { render() { return ( <li> <div> <span>{this.props.value}</span> { !this.props.isEditing && (<button onClick={this.props.toggleIsEditing}> Edit </button>) } { this.props.isEditing && (<div> <span>...Editing</span> <button onClick={this.props.toggleIsEditing}> Stop </button> </div>) } </div> </li> ); } } ReactDOM.render(<List />, document.getElementById('app')); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <body> <div id="app" /> </body> 

#1楼 票数:0

您在将toggleIsEditing传递给子组件时未绑定父作用域

  <Item value={val} toggleIsEditing={this.toggleIsEditing.bind(this)} isEditing={this.state.isEditing}/> 

#2楼 票数:0 已采纳

我对问题重新表述时,通过重新考虑实现来找出解决方案。 我的原始实现存在一些问题:

  • List类的非生命周期方法中的this不受类范围的约束(如@ZhangBruce在其回答中指出的那样)。
  • List的状态管理逻辑缺少其他属性来处理用例。

另外,我认为向Item组件本身添加state对于正确传播更新很重要。 具体来说,添加state.val是关键(据我了解)。 可能还有其他方法(可能更简单),在这种情况下,我很想知道,但是与此同时,这是我的解决方案:

 const items = ['foo', 'bar']; class List extends React.Component { constructor(props) { super(props); this.state = { editingFieldIndex: -1 }; } setEdit = (index = -1) => { this.setState({ editingFieldIndex: index }); } render() { return ( <ul> {items.map((val, index) => ( <Item val={val} index={index} setEdit={this.setEdit} editingFieldIndex={this.state.editingFieldIndex} /> ))} </ul> ); } } class Item extends React.Component { constructor(props) { super(props); this.state = { val: props.val }; } save = (evt) => { this.setState({ val: evt.target.value }); } render() { const { index, setEdit, editingFieldIndex } = this.props; const { val } = this.state; const shouldShowEditableValue = editingFieldIndex === index; const shouldShowSaveAction = editingFieldIndex === index; const shouldHideActions = editingFieldIndex !== -1 && editingFieldIndex !== index; const editableValue = ( <input value={val} onChange={(evt) => this.save(evt)}/> ) const readOnlyValue = ( <span>{val}</span> ) const editAction = ( <button onClick={() => setEdit(index)}> Edit </button> ) const saveAction = ( <button onClick={() => setEdit()}> Save </button> ) return ( <li> <div> { console.log(`index=${index}`) } { console.log(`editingFieldIndex=${editingFieldIndex}`) } { console.log(`shouldHideActions=${shouldHideActions}`) } { shouldShowEditableValue ? editableValue : readOnlyValue } { !shouldHideActions ? shouldShowSaveAction ? saveAction : editAction : "" } </div> </li> ); } } ReactDOM.render(<List />, document.getElementById('app')); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <body> <div id="app" /> </body> 

  ask by rtorres translate from so

未解决问题?本站智能推荐:

1回复

使用React中的地图渲染列表项

我有以下数组, 这是我希望渲染数组的React组件。 这就是我宣布道具的方式。 这就是我在主容器内传递道具的方式。 列表没有呈现,我没有得到任何数组。 任何帮助赞赏。
2回复

反应原生平面列表不呈现项目

我希望你一切都好 我的 react-native 项目遇到了一些奇怪的事情,某些页面中的 FlatList 项目没有显示,即使我在 console.log(json.items) 时可以看到它们。 今天早些时候,一切正常。 所有页面都在我的设备上显示了它们应该显示的列表。 然后我开始在零食上创建一
3回复

React 组件正在重新渲染从状态中删除的项目

这很难解释,所以我会尽力而为! 我的目标 我一直在学习 React 并决定尝试从头开始构建一个待办事项列表应用程序。 我想实现一个“推送通知”系统,当你说将待办事项标记为完成时,它会在左下角弹出,例如“遛狗已更新”。 几秒钟后,它将从 UI 中删除。 相当简单的目标,在大多数情况下我已经让它工作
1回复

反应不呈现状态变化

这是代码: API调用工作正常,并且我正在将数据恢复为当前状态。 但是,重新渲染没有发生。 console.log(a)首先返回数组长度0,扩展时返回适当长度。
1回复

反应状态不渲染

我要做的就是将状态“草稿”渲染到H1标签上,而它根本不会这样做! 它让我发疯。 我究竟做错了什么? 最初的H1标签“我可以看到”可以看到,但是第二对根本没有出现。
1回复

反应状态更改不是渲染

我对React很新,我遇到的问题是我的初始状态是渲染,但是当状态通过AJAX调用时调用(成功)不会导致函数再次渲染。 那么,'getInitialState'设置一个静态的类别列表,'componentDidMount'从我的API中获取一个新列表。 调用正确执行并触发成功,因此我不知道为什
3回复

反应渲染和状态

虽然我了解状态的使用和呈现组件,但我在这种特殊情况下遇到了麻烦。 我有一组问题,我想从 0 到问题长度(在我的情况下为 8)中选择一个随机数,而不重复数字。 我已经弄清楚了这个逻辑,但是当我将随机数分配给状态时,似乎重新渲染导致此逻辑每次都重置,因此数字重复。 我需要然后链接到带有相应随机数的问
3回复

反应状态未呈现到屏幕

我在构造函数中创建了一个state ,在componentDidmount创建了setState ,当我尝试将该状态对象render到屏幕时,它抛出错误,服务器im正在使用的是node API ,并且其他所有东西都工作正常。 帮我解决这个问题 app.js(反应) 我从节点API