简体   繁体   English

React 不会使用初始值的循环数组更改输入值

[英]React doesn't change input value with looping array for initial value

How can i update a value for input text in a state array?如何更新状态数组中输入文本的值? Here is the code that I am currently using:这是我目前使用的代码:

This is for initial state react hooks这是用于初始状态反应钩子

const [kernelSize, setKernelSize] = useState(3)
const [kernel, setKernel] = useState([])

Input range for size of kernel内核大小的输入范围

<input type="range" step="2" name="range" min="3" max="7" value={kernelSize} className="slider" onChange={(e) => handleKernel(e)} /> <input type="range" step="2" name="range" min="3" max="7" value={kernelSize} className="slider" onChange={(e) => handleKernel(e)} />

This is for handleKernel function这是用于 handleKernel 函数

const handleKernel = (e) => {
    setKernelSize(e.target.value)
    let kernel = []
    for (let i = 0; i < e.target.value; i++) {
        kernel.push([])
        for (let j = 0; j < e.target.value; j++) {
            kernel[i].push(1)
        }
    }
    setKernel(kernel)
}

This is for looping input text based size/length from input range这是用于从输入范围循环输入文本的大小/长度

{
kernel.map((value, index) => {
    return (
        <div className="row mt-3" key={`${index}_${value}`}>
            {
                value.map((value_2, index_2) => {
                    return (
                        <div className="input-wrap" key={`${index_2}_${value_2}`}>
                            <input type="text" id="" className="form-control" value={value_2} onChange={(e) => updateKernel(e, index, index_2)} />
                        </div>
                    )
                })
            }
        </div>
    )
})}

This is for updateKernel function这是用于 updateKernel 功能

const updateKernel = (e, index, index_2) => () => {
    let kernelCopy = [...kernel];
    kernelCopy[index][index_2] = e.target.value;
    setKernel(kernelCopy);
}

Looks like the issue here is that you aren't also shallow copying the nested inner array that is being updated.看起来这里的问题是您还没有浅复制正在更新的嵌套内部数组。

const updateKernel = (e, index, index_2) => {
  // use a functional state update to update from previous state
  setKernel((kernel) =>
    // shallow copy outer array
    kernel.map((outerEl, i1) =>
      i1 === index
        // shallow copy inner array on index match
        ? outerEl.map((innerEl, i2) =>
            // update at index match or return current
            i2 === index_2 ? e.target.value : innerEl 
          )
        : outerEl
    )
  );
};

Update更新

Inputs lose focus because of the way you've defined the React keys.由于您定义 React 键的方式,输入失去了焦点。 The keys use the index and current value, both of which are probably the two worst values you could choose for React keys.键使用索引和当前值,这两个值可能是您可以为 React 键选择的两个最差值。 The issue is that upon each change the key is now a different value and React unmounts the previous input and mounts a new one.问题是每次更改时,键现在都是不同的值,React 会卸载之前的输入并安装新的输入。

The solution is to use stable keys that persist and live for the entire life of the data it's representing in React.解决方案是使用稳定的密钥,这些密钥在它在 React 中表示的数据的整个生命周期中都存在。 For this I suggest using objects with an id property for the key, and a value property for the value being rendered.为此,我建议使用带有键的id属性和呈现的值的value属性的对象。

Here's a full code example using the uuid package to generate GUIds.这是使用uuid 包生成 GUId 的完整代码示例。

import { v4 as uuidV4 } from "uuid";

function App() {
  const [kernelSize, setKernelSize] = useState(3);
  const [kernel, setKernel] = useState([]);

  useEffect(() => {
    let kernel = [];
    for (let i = 0; i < kernelSize; i++) {
      kernel.push({
        id: uuidV4(), // <-- generate a row id
        value: []
      });
      for (let j = 0; j < kernelSize; j++) {
        kernel[i].value.push({
          id: uuidV4(), // <-- generate element id
          value: 1
        });
      }
    }
    setKernel(kernel);
  }, [kernelSize]);

  const handleKernel = (e) => {
    setKernelSize(e.target.value);
  };

  const updateKernel = (index, index2) => (e) => {
    setKernel((kernel) =>
      kernel.map((outerEl, i1) =>
        i1 === index
          ? {
              ...outerEl,
              value: outerEl.value.map((innerEl, i2) =>
                i2 === index2
                  ? {
                      ...innerEl,
                      value: e.target.value
                    }
                  : innerEl
              )
            }
          : outerEl
      )
    );
  };

  return (
    <div className="App">
      <input
        type="range"
        step="2"
        name="range"
        min="3"
        max="7"
        value={kernelSize}
        className="slider"
        onChange={handleKernel}
      />

      <div>
        {kernel.map((row, index) => {
          return (
            <div className="row mt-3" key={row.id}> // <-- use id as React key
              {row.value.map(({ id, value }, index_2) => {
                return (
                  <span className="input-wrap" key={id}> // <-- use id as React key
                    <input
                      style={{
                        width: "2rem"
                      }}
                      type="text"
                      id=""
                      className="form-control"
                      value={value}
                      onChange={updateKernel(index, index_2)}
                    />
                  </span>
                );
              })}
            </div>
          );
        })}
      </div>
    </div>
  );
}

编辑 react-doesnt-change-input-value-with-looping-array-for-initial-value

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

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