简体   繁体   English

反应中的 onChange 没有按我预期的那样工作

[英]onChange in react not working as I would expect

given this datatype for tables an array of object of objects:给定表的此数据类型对象的对象数组:

[
    {
        "1": {
            "1": "Item s ",
            "2": "Manufacturer ",
            "3": "Mir s ",
            "4": "Decoription ",
            "5": "Contents ",
            "6": "UOM ",
            "7": "Total Ship Total Qty ",
            "8": "% of Purohasec ",
            "9": "Involoe Count ",
            "10": "K Brand "
        },
        "2": {
            "1": "fdsa ",
            "2": "fdsa fdsa ",
            "3": "16-fsd ",
            "4": "fds fdsa TW fsda",
            "5": "100 ",
            "6": "B) ",
            "7": "6 ",
            "8": "0.17 ",
            "9": "3 ",
            "10": ""
        },
      }, 
    ....
]

I have this component that displays a "row" to be edited.我有这个显示要编辑的“行”的组件。 I am displaying the form and table backed by the json data (above), thinking I work with the table and set it in state, the the view re-renders and gives me the change.我正在显示由 json 数据(上图)支持的表单和表格,认为我使用表格并将其设置为状态,视图重新呈现并给我更改。 The datatype above will be in the above format, but the headers, number of tables, fields could all change from run to run.上面的数据类型将采用上述格式,但标题、表数、字段都可能在每次运行中发生变化。 Also I don't have much control over the data type.此外,我对数据类型没有太多控制权。 The table being passed as a prop is tablesCopy you see below in the cellChange.作为道具传递的表格是您在下面的 cellChange 中看到的 tablesCopy。

const [tablesCopy, setTablesCopy] = useState<any>({});

... ...

const InvRow = ({ rowTarget, clearEditRow, table, cellChange }: { rowTarget: string, clearEditRow: Function, table: any; cellChange: Function; }) => {
  const tt = tableTarget(rowTarget);

  const editRow = [];

  if (tt) {
    const labels = table[tt.table][1];
    const values = table[tt.table][tt.row];

    const keys = Object.keys(labels);
    for (let key of keys) {
      const name = `t_${tt.table}_r_${tt.row}_c_${key}`;
      editRow.push(<tr>
        <td>{labels[key]}</td>
        <td><Input type="text" value={values[key]} name={name} id={name} onChange={(e) => cellChange(e)} /></td>
      </tr>);
    }
  }

  return (
    <>
      <Table>{editRow}</Table>
      <div>
        <Button onClick={(e) => clearEditRow(e)} color="primary" size="lg">Close</Button>
      </div>
    </>

  );
};

my on cellChange method is the following, and it is fired correctly with expected inputs:我的关于 cellChange 的方法如下,它用预期的输入正确触发:

  const cellChange = (e: React.BaseSyntheticEvent) => {

    const tt = tableTarget(e.target.id);
    console.log("cellChange -> tt", tt);
    tablesCopy[tt.table][tt.row][tt.cell] = e.target.value;
    setTablesCopy(tablesCopy);

  };

however, in the display, the old values are not getting replaced by the onChange event, though in the console, i can see the event getting fired with the correct values.然而,在显示中,旧值没有被 onChange 事件替换,尽管在控制台中,我可以看到该事件被正确的值触发。

Any suggestion to implement this onChange better, or a differnt tact i should be taking?有什么建议可以更好地实施这个 onChange,或者我应该采取不同的策略?

edit: adding my useEffect initialization:编辑:添加我的 useEffect 初始化:

  useEffect(() => {
    const fetchData = async () => {
      const path = "/tables.json";
      const response = await fetch(path);
      const tables: any = await response.json();
      setTablesOrig(tables);
      setTablesCopy({ ...tables });
      const tableKeys = Object.keys(tablesCopy);
      setNumOfTables(tableKeys.length);

    };
    fetchData();
  }, []);

You should clone your data object.您应该克隆您的数据对象。 If you're using just string , number and bool in your table, this should work just fine:如果您在表中只使用stringnumberbool ,这应该可以正常工作:

const cellChange = (e: React.BaseSyntheticEvent) => {

    const tt = tableTarget(e.target.id);
    console.log("cellChange -> tt", tt);
    var tables = JSON.parse(JSON.stringify(tablesCopy)); // <- clone
    tables[tt.table][tt.row][tt.cell] = e.target.value;
    setTablesCopy(tables);

  };

see other options of deep object clone here: What is the most efficient way to deep clone an object in JavaScript?在此处查看深度对象克隆的其他选项: 在 JavaScript 中深度克隆对象的最有效方法是什么?

UPD: As mentioned in comments you could use spread syntax to copy, however, it's not enought to do {...tablesCopy} but you should also clone that table, row and cell you're changing. UPD:正如评论中提到的,您可以使用扩展语法进行复制,但是,仅执行{...tablesCopy}{...tablesCopy}但您还应该克隆要更改的表、行和单元格。 So right way would be as follows:所以正确的方法如下:

const cellChange = (e: React.BaseSyntheticEvent) => {

    const tt = tableTarget(e.target.id);
    console.log("cellChange -> tt", tt);

    var tables = {
        ...tablesCopy,
        [tt.table]: {
            ...tablesCopy[tt.table],
            [tt.row]: {
                ...tablesCopy[tt.table][tt.row],
                [tt.cell]: e.target.value
            }
        }
    };
    setTablesCopy(tables);

  };

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM