子组件应将类似的子组件呈现为父组件中的兄弟

时间:2019-09-07 19:56:24

标签: reactjs

我是新来的要做出反应的人,所以请忍受任何非技术性的话。

我有一个显示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>
        )
    }

}

2 个答案:

答案 0 :(得分:1)

听起来好像您想在单击按钮后克隆行。让我知道这是否是您想要的。

希望这会有所帮助!

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>

答案 1 :(得分:1)

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

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

查看有效的沙箱:https://codesandbox.io/s/inspiring-wave-bpv7f

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

考虑这样的示例;

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. 双击单元格将切换属于父状态的项的edit属性。
  4. 如果编辑为true,则显示输入,如果不仅仅是 普通表格单元格。