【问题标题】:Child component should render similar child component as sibling in parent component子组件应该将类似的子组件渲染为父组件中的兄弟组件
【发布时间】:2020-01-10 05:14:41
【问题描述】:

我是新手,所以请忍受任何非技术性的话。

我有显示table 标头的父组件,现在下一个是具有表的td 以及一个td 的子组件,当用户单击添加button 时添加button。应该将类似的子组件添加为前一个子组件的兄弟组件,并且应该继续此过程。


子组件:

class ChildComp extends React.Component{

    state = {
        Avalue: {value: ''},
        Bvalue: {value: ''},
        Cvalue: {value: ''},
        Dvalue: {value: ''},
        Evalue: {value: ''},
        Fvalue: {value: ''},
        Gvalue: {value: ''},
    }

    AddanotherSimilarChildcomp=(e)=>{
    e.preventDefault();
        const historyData = {
        A: this.state.A.value,
        B:this.state.B.value,
        C: this.state.C.value,
        D: this.state.D.value,
        E: this.state.E.value,
        F: this.state.F.value,
        G: this.state.G.value,
        }
    console.log(historyData);
      //and should render another similar ChildComp component below the one in which the current ChildComp is present
    }

    handleChange=(e)=>{
        e.preventDefault();
        const target = e.target;
        const inputName = target.name;
        const inputValue = target.value;
        this.setState({
        [inputName] : {
            value: inputValue,
        }
    }); 
    }

    render(){
        return(
            <tbody id="first-table-row">
                <tr>
                <td data-th="A"><input type="text" minmax="40" name="A" value={this.state.a.value} onChange={this.handleChange} /></td>
                <td data-th="B"><input type="date" minmax="40" name="B" value={this.state.B.value} onChange={this.handleChange} /></td>
                <td data-th="C"><input type="text" minmax="225" name="C" value={this.state.C.value} onChange={this.handleChange} /></td>
                <td data-th="D"><input type="text" minmax="40" name="D"value={this.state.D.value} onChange={this.handleChange} /></td>
                <td data-th="E"><input type="text" minmax="40" name="E" value={this.state.E.value}  onChange={this.handleChange} /></td>
                <td data-th="F"><input type="text" minmax="40" name="F" value={this.state.F.value} onChange={this.handleChange} /></td>
                <td data-th="G">
                <div id="samerow">
                    <span>{this.props.somedata}</span>
                    <input type="text" minmax="40" name="G"value={this.state.G.value} onChange={this.handleChange} />
                </div>
                </td>
                <td className="save" ><button id="save-btn" onClick={this.AddanotherSimilarChildcomp} type='button'>Add</button></td>
                </tr>
            </tbody>
        )
    }
}

父组件:

class ParentComponent extends React.PureComponent{

    render(){
    return(
            <div className='table-center' id='table1'>
                <table className="rwd-table" id="tblBlah" >
                    <tbody>
                        <tr>
                            <th>A</th>
                            <th>B</th>
                            <th>C</th>
                            <th>D</th>
                            <th>E</th>
                            <th>F</th>
                            <th>G</th>
                            <th>&nbsp;</th>
                        </tr>
                    </tbody>
                    <ChildComp/>  
                </table>
            </div>
        )
    }

}

【问题讨论】:

  • 很难理解你想要发生什么。所以你想要在每一行中添加一个新行的按钮,这是单击按钮的行的克隆?

标签: reactjs


【解决方案1】:

我认为您的组件树的逻辑过于复杂。我就是这样解释你的问题的。

  • 您有一个父组件,它呈现带有标题的表格。
  • 每个子组件都是一个表格行。
  • 您有一个应该添加更多行的按钮(子组件)。
  • 属于每一行的表格单元格应该是可编辑的(因此 输入)。

查看工作沙箱:https://codesandbox.io/s/inspiring-wave-bpv7f

让父组件管理数据集是最有意义的。因此,所有涉及从数据集中更新或添加内容的逻辑都应该属于父组件,而不是子组件。

考虑这样的例子;

Parent.js

class App extends React.Component {
  state = {
    headers: ["name", "age", "job", "salary"],
    data: [
      [
        { name: "Bobby Hill", editting: false },
        { age: 13, editting: false },
        { job: "student", editting: false },
        { salary: 0, editting: false }
      ]
    ]
  };

  createHeaders = () => {
    const { headers } = this.state;
    return headers.map(item => <th className="table-header">{item}</th>);
  };

  createBody = () => {
    const { data } = this.state;

    return data.map((row, index) => (
      <Child data={row} rowIndex={index} toggleEdit={this.toggleEdit} />
    ));
  };

  addRow = () => {
    const { data } = this.state;

    const rowTemplate = [
      { name: "", editting: true },
      { age: "", editting: true },
      { job: "", editting: true },
      { salary: "", editting: true }
    ];

    this.setState({
      data: [...data, rowTemplate]
    });
  };

  toggleEdit = (rowIndex, cellIndex) => {
    const dataCopy = [...this.state.data];

    const itemToUpdate = dataCopy[rowIndex][cellIndex];

    itemToUpdate.editting = !itemToUpdate.editting;

    this.setState({
      data: dataCopy
    });
  };

  render() {
    return (
      <div className="table-center" id="table1">
        <table className="rwd-table" id="tblBlah">
          <tbody>
            <tr>{this.createHeaders()}</tr>
            {this.createBody()}
          </tbody>
        </table>
        <button onClick={this.addRow}>Add Row</button>
      </div>
    );
  }
}

在父组件中我们有:

  1. 我们州的一个数据集,它是一个数组数组。每个数组 与表行有关。
  2. 当我们遍历数据集时,我们将一个数组传递给每个 Child 组件,它将呈现行。
  3. addRow 函数将向我们的数据集添加一个新数组, 包含对应于每个表头/属性的对象。
  4. toggleEdit 函数帮助我们在每个编辑模式之间切换 细胞。

Child.js

import React from "react";

const Child = ({ data, rowIndex, toggleEdit }) => {
  return (
    <tr>
      {data.map((cell, cellIndex) => (
        <td
          className="table-cell"
          onDoubleClick={() => toggleEdit(rowIndex, cellIndex)}
        >
          {cell.editting ? (
            <input value={Object.values(cell)[0]} />
          ) : (
            <span>{Object.values(cell)[0]}</span>
          )}
        </td>
      ))}
    </tr>
  );
};

export default Child;

现在在子组件中:

  1. 它使用传递给它的数据(数组)是一个道具,并且 使用它来呈现行。
  2. 对于数组中的每个项目(对象),它都会创建一个表格单元格以 显示值。
  3. 双击单元格将切换属于父状态的项目的编辑属性。
  4. 如果编辑为真,则显示一个输入,如果不只是一个 普通表格单元格。

【讨论】:

    【解决方案2】:

    听起来您想在单击按钮后克隆行。如果这就是您要查找的内容,请告诉我..

    希望这会有所帮助!

    class ParentComponent extends React.Component {
      render() {
        return (
          <div>
            <table>
              <tbody>
                <tr>
                  <th>A</th>
                  <th>B</th>
                  <th>C</th>
                  <th>D</th>
                  <th>E</th>
                  <th>F</th>
                  <th>G</th>
                  <th>&nbsp;</th>
                </tr>
              </tbody>
              <ChildComp
                rows={[
                  [1, 2, 3, 4, 5, 6, 7],
                  [8, 9, 10, 11, 12, 13, 14],
                  [14, 15, 16, 17, 18, 19, 20]
                ]}
              />
            </table>
          </div>
        );
      }
    }
    
    class ChildComp extends React.Component {
      state = {
        tableRows: []
      };
    
      componentDidMount() {
        this.setState({ tableRows: this.props.rows });
      }
    
      addNewRow = (rowToClone, index) => event => {
        let newRows = [...this.state.tableRows];
        newRows.splice(index, 0, rowToClone.map(i => `${i}` + `${i[0] || i}`));
        this.setState({ tableRows: newRows });
      };
    
      render() {
        return (
          <tbody>
            {this.state.tableRows.map((row, index) => {
              return (
                <tr>
                  {row.map(i => <td>{i}</td>)}
                  <td>
                    <button onClick={this.addNewRow(row, index + 1)}>
                      Clone Row
                    </button>
                  </td>
                </tr>
              );
            })}
          </tbody>
        );
      }
    }
    
    ReactDOM.render(<ParentComponent />, document.body);
    table, th, tr, td {
      border: 1px solid black;
    }
    
    table {
        border-collapse: collapse;
    }
    
    td {
      width: 50px;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.9.0/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-09
      • 1970-01-01
      • 2017-04-20
      • 1970-01-01
      相关资源
      最近更新 更多