代码之家  ›  专栏  ›  技术社区  ›  Kyan

为迭代中的输入字段分配唯一引用

  •  0
  • Kyan  · 技术社区  · 5 年前

    我有一个表,它由一个提取的映射生成,并为每个映射生成一行 payer 在这张地图里。

    每行包含 payer name ,两个输入字段和一个按钮 onClick 事件处理程序。

    提交时,系统应

    • payer id ,
    • transaction id (收集自 props )
    • payer value (与付款人对象无关的自定义字段)
    • payer notes (同样,与付款人对象无关的自定义字段)

    POST 这是一个终结点。

    我正在寻找一种方法将正确的参数传递给 一次点击 处理程序-当生成的输入量不确定时-因为我的当前解决方案只注册映射中的最后一个字段。

    您将看到我在输入元素中使用了一些引用 - 我试着用它们来看看我是否能取得某种效果,但是我没有运气。 - 是的,它们是在构造函数中声明的 .

    建造师

    constructor(props) {
        super(props);
        this.state = {
            payers: []
        }
    
        this.closeModal = this.closeModal.bind(this);
        this.confirmTransaction = this.confirmTransaction.bind(this);
    }
    

    相关 render()

    render() {
    
        const tableHeader = (
            <thead>
                <tr>
                    <td>Name</td>
                    <td>Value</td>
                    <td>Notes</td>
                    <td></td>
                </tr>
            </thead>
        )
    
        const payersList = this.state.payers.map(payer => {
            return (
                <React.Fragment>
                    <tr>
                        <td className="font-italic" key={payer.id}>{payer.name}</td>
                        <td>
                            <input className="form-control form-control-sm" type="text" placeholder={this.props.transaction.debit} ref={value => this.payerValue = value} />
                        </td>
                        <td>
                            <input className="form-control form-control-sm" type="text" ref={notes => this.payerNotes = notes} />
                        </td>
                        <td>
                            <button onClick={() => this.confirmTransaction(this.props.transaction.id, payer.name, this.payerValue.value, this.payerNotes.value)}>OK</button>
                        </td>
                    </tr>
                </React.Fragment>
            )
        });
    

    确认事务处理程序

    confirmTransaction(id, name, value, notes) {
        alert(`This will set ${name} as a payer for transaction ${id} for the value of ${value} with the notes ${notes}`)
    }
    

    示例输出(缺少$值和$注释)

    Output

    1 回复  |  直到 5 年前
        1
  •  1
  •   Momen Zalabany    5 年前

    我会把它分成两个部分和一个容器。

    1. listcontainer:将保留逻辑和呈现列表
    2. <ListComponent payers={[..payers]} onClick={this.setPayer}/> :这将呈现rowcomponent
    3. <RowComponent payer={{id:1}} onClick={props.onClick} /> :这将呈现一行。

    现在props.onclick是一个函数 ListContainer 在rowcomponent中,您应该用您拥有的对象调用这个函数。

    例子: https://codesandbox.io/s/peaceful-northcutt-jn769?fontsize=14

    祝你好运:)

    import React, { useState, useEffect } from "react";
    import ReactDOM from "react-dom";
    
    function Row({ payer, onClick }) {
      const [value, onChange] = useState(payer.value);
    
      // dont forget to update value if parent changed for somereason
      useEffect(() => {
        if (payer.value !== value) {
          onChange(payer.value);
        }
      }, [payer]);
    
      return (
        <li>
          <label>{payer.name}</label>
          <input value={value} onChange={e => onChange(e.target.value)} />
          <button onClick={e => onClick({ ...payer, value })}>save</button>
        </li>
      );
    }
    
    function ListComponent({ payers, onClick }) {
      return (
        <ul>
          {payers.map(payer => (
            <Row key={payer.id} payer={payer} onClick={onClick} />
          ))}
        </ul>
      );
    }
    
    function ListContainer() {
      const [payers, addPayer] = useState([
        { id: 1, name: "a", value: 1 },
        { id: 2, name: "b", value: 2 }
      ]);
      function setPayer(payer) {
        alert("payer is " + JSON.stringify(payer));
        addPayer(payers.filter(i => i.id !== payer.id).concat(payer));
      }
    
      return (
        <div className="App">
          <ListComponent onClick={setPayer} payers={payers} />
          <pre>{JSON.stringify(payers, null, 2)}</pre>
        </div>
      );
    }
    
    const rootElement = document.getElementById("root");
    ReactDOM.render(<ListContainer />, rootElement);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
    <div id="root"></div>