反应功能组件:第一个值之后无法继续在输入元素中键入值

KAR*_*N.A 0 javascript reactjs react-functional-component

我正在尝试通过输入元素更新反应功能组件中的值,但在第一个值之后我无法输入

我的代码:

import React from "react";
import "./App.css";

const { useState } = React;
function App() {
    const [items, setItems] = useState([
        { value: "" },
        { value: "" },
        { value: "" },
    ]);
    const [count, setCount] = useState(0);
    const Item = React.memo(({ id, value, onChange }) => {
        return (
            <div className="item">Item
                <input
                    onChange={(e) => onChange(id, e.target.value)}
                    value={value}
                />
            </div>
        );
    });
    return (
        <div className="app">
            <h1>Parent</h1>
            <p style={{marginTop: '20px'}}>Holds state: {count}, Does't passes to it items</p>
            <p style={{marginTop: '20px'}}>{JSON.stringify(items)}</p>
            <button onClick={() => setCount((prev) => prev + 1)} style={{marginTop: '20px'}}>
                Update Parent
            </button>
            <ul className="items" style={{marginTop: '20px'}}>
                {items.map((item, index) => {
                    return (
                        <Item
                            key={index}
                            id={index}
                            value={item.value}
                            onChange={(id, value) =>
                                setItems(
                                    items.map((item, index) => {
                                        return index !== id
                                            ? item
                                            : { value: value };
                                    })
                                )
                            }
                        />
                    );
                })}
            </ul>
        </div>
    );
}

export default App;
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

nul*_*ptr 5

您应该将Item声明移到组件之外App。在另一个组件中声明一个组件几乎总是一个坏主意。解释如下。

import React, { useState } from "react";

const Item = React.memo(({ id, value, onChange }) => {
  return (
    <div className="item">
      Item
      <input onChange={(e) => onChange(id, e.target.value)} value={value} />
    </div>
  );
});

function App() {
  const [items, setItems] = useState([
    { value: "" },
    { value: "" },
    { value: "" }
  ]);
  const [count, setCount] = useState(0);

  return (
    <div className="app">
      <h1>Parent</h1>
      <p style={{ marginTop: "20px" }}>
        Holds state: {count}, Does't passes to it items
      </p>
      <p style={{ marginTop: "20px" }}>{JSON.stringify(items)}</p>
      <button
        onClick={() => setCount((prev) => prev + 1)}
        style={{ marginTop: "20px" }}
      >
        Update Parent
      </button>
      <ul className="items" style={{ marginTop: "20px" }}>
        {items.map((item, index) => {
          return (
            <Item
              key={index}
              id={index}
              value={item.value}
              onChange={(id, value) =>
                setItems(
                  items.map((item, index) => {
                    return index !== id ? item : { value: value };
                  })
                )
              }
            />
          );
        })}
      </ul>
    </div>
  );
}

export default App;
Run Code Online (Sandbox Code Playgroud)

当一个组件定义位于另一个组件内部时,每次父组件重新渲染时, React 都会重新声明内部组件。这意味着,内部组件所持有的任何状态都将丢失。在您的情况下,由于每次都有一个全新的组件,输入与之前渲染中的输入不同。这意味着input先前渲染中处于焦点的内容不再存在,并且新输入不再具有焦点。

你也应该改变

setItems(
    items.map((item, index) => {
        return index !== id ? item : { value: value };
    })
)
Run Code Online (Sandbox Code Playgroud)

    prev.map((item, index) => {
        return index !== id ? item : { value: value };
    })
)
Run Code Online (Sandbox Code Playgroud)

当新状态依赖于旧状态值时,最好使用函数表示法来设置状态。

  • @KARTHIKEYAN.A 我已编辑帖子以添加一些解释 (2认同)