【问题标题】:React - mapping data to rows that are formed during a map functionReact - 将数据映射到在映射函数期间形成的行
【发布时间】:2016-06-17 04:08:58
【问题描述】:

我有一个名为 Cells 的组件,它使用从通量存储中获取的数据进行渲染。我的问题是我想将此数据呈现到特定行,但由于我呈现行的方式(它们是动态的,因此您可以将它们添加到表中),我正在努力为单元格组件提供行标识符可以渲染成。我希望这是有道理的!

代码如下:

细胞组件:

import React from 'react';

export default class Cells extends React.Component {
    render() {
        return (
            <td>{this.props.value}</td>
        );
    }
}

表格组件:

    import React from 'react';
    import TableHeader from './TableHeader.jsx';
    import Cells from './Cells.jsx';
    import RowForm from './RowForm.jsx';
    import {createRow} from '../../actions/DALIActions';
    import AppStore from '../../stores/AppStore';

    export default class Table extends React.Component {
        state = {rows: [], cellValues: [], isNew: false, isEditing: false};
        updateState = () => this.setState({cellValues: AppStore.getCellValues()});

        componentWillMount() {
            AppStore.addChangeListener(this.updateState);
        }

        handleAddRowClickEvent = () => {
            let rows = this.state.rows;
            rows.push({isNew: true});
            this.setState({rows: rows});
        };

        handleEdit = (row) => {
            this.setState({isEditing: true});
        };

        editStop = () => {
            this.setState({isEditing: false});
        };

        handleSubmit = (access_token, id, dataEntriesArray) => {
            createRow(access_token, id, dataEntriesArray);
        };

        componentWillUnmount() {
            AppStore.removeChangeListener(this.updateState);
        }

        render() {

            let {rows, cellValues, isNew, isEditing} = this.state;

            let headerArray = AppStore.getTable().columns;

            let cells = this.state.cellValues.map((value, index) => {
                return (
                    <Cells key={index} value={value.contents} />
                );
            });

            return (
                <div>
                    <div className="row" id="table-row">
                        <table className="table table-striped">
                            <thead>
                                <TableHeader />
                            </thead>
                            <tbody>
//////////// This is where the render of the data would happen/////////////
                                {rows.map((row, index) => this.state.isEditing ?
                                    <RowForm formKey={index} key={index} editStop={this.editStop} handleSubmit={this.handleSubmit} /> :
                                    <tr key={index}>
                                        {this.state.cellValues ? cells : null}
                                        <td>
                                            <button className="btn btn-primary" onClick={this.handleEdit.bind(this, row)}><i className="fa fa-pencil"></i>Edit</button>
                                        </td>
                                    </tr>
                                )} 
                   ///////////////End/////////////////
                            </tbody>
                        </table>
                    </div>
                    <div className="row">
                        <div className="col-xs-12 de-button">
                            <button type="button" className="btn btn-success" onClick={this.handleAddRowClickEvent}>Add Row</button>
                        </div>
                    </div>
                </div>
            );
        }
    }

我知道这可能不是实现我想要的最佳方式(任何关于这方面的提示也将不胜感激),但这是我目前必须使用的!

任何帮助将不胜感激,尤其是示例!

感谢您的宝贵时间!

【问题讨论】:

  • 您在控制台中遇到的错误是什么?
  • 我没有收到错误,每一行的数据都是一样的!
  • 我编辑了我的答案,你需要在行单元格上传递 apply map 函数

标签: reactjs reactjs-flux


【解决方案1】:

我建议您将单元格数据放在单独的行数据中方式,以便您的数据结构看起来像这样:

rows = [
  { rowID: 100, cells: [
      { cellID: 101, value: 'data' },
      { cellID: 102, value: 'data' }
    ]
  },
  { rowID: 200, cells: [
      { cellID: 201, value: 'data' },
      { cellID: 202, value: 'data' }
    ]
  }
]

这样,您可以传递每行的 cellValues,这样您就可以每行有不同的单元格。

&lt;Row&gt;创建一个单独的组件,它会渲染:

return 
  <tr>
    {this.props.cells.map( cell => { 
        return <Cell key={cell.cellID} value={cell.value} />
    })}
  </tr>

并将主渲染中的&lt;tr&gt; 位更改为:

<Row key={row.keyID} cells={row.cells}/>

最后:使用索引作为键是一个坏主意,如key={i}。使用唯一标识单元格/行的内容的键。

更新:一个典型的情况是单元格或行首先在前端创建,并且只有在发布到数据库后才能获得它们的数据库ID。
仍然为密钥获取唯一 ID 的选项是:

  • 在反应中创建单元格或行时,以时间戳的形式为单元格/行提供唯一的 ID。从数据库取回响应后,将时间戳替换为官方数据库密钥。 (这是您进行乐观更新的时候:暂时显示新行,直到数据库为您提供正式的行)。
  • 不显示行/单元格,直到您从具有官方 ID 的服务器返回响应
  • 通过散列所有单元格/行内容的内容创建唯一键(如果您非常确定单元格/行内容不太可能相同)

希望这会有所帮助。

【讨论】:

  • 抱歉回复晚了!我的问题是,在将特定行的数据提交到我的数据库之前,不会获取行和单元格值的 ID。因此,一旦保存了行本身,该行就会获得一个 id,并且每个单元格值也会被赋予一个。分配它们的最佳方法是存储这些值,然后将行的状态更新为您建议的状态吗?
  • 更新了解决这个问题的答案
  • 是的,我最终做到了,现在可以了,谢谢!
【解决方案2】:

您需要将row 传递给单元格渲染方法:

  {rows.map((row, index) => this.state.isEditing ?
       <RowForm formKey={index} key={index} editStop={this.editStop} handleSubmit={this.handleSubmit} /> :
       <tr key={index}>
         {(row.cellValues || []).map((value, index) => {
            return (
                <Cells key={index} value={value.contents} />
          )})
         }
         <td>
           <button className="btn btn-primary" onClick={this.handleEdit.bind(this, row)}><i className="fa fa-pencil"></i>Edit</button>
         </td>
       </tr>
  )} 

希望对您有所帮助!

【讨论】:

  • 在键中使用映射索引是个坏主意,应该避免。
  • @wintvelt 是的,我知道,但这就是他的问题,我试图用最小的变化来解决他的问题
  • 感谢您的回答。当我尝试使用您的答案时,它仍然只将最新输入的数据保存到一行中,因此如果我将数据输入到一行中,则所有行都相同,如果我更改它,所有行中的数据都会更改为我最最近装的。
  • 我知道你要去哪里,但我收到“无法读取未定义的地图”的错误,因为在第一个实例中 cellValues 未填充是因为其中没有数据。
  • 如果您可以发布服务器响应,那么我可以提供更多帮助
猜你喜欢
  • 2020-05-16
  • 1970-01-01
  • 2021-09-24
  • 1970-01-01
  • 2017-05-01
  • 2022-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多