react:根据 props 的变化更新受控输入的值

问题描述 投票:0回答:1

我打赌已经被回答了一百万次,但我还没有在谷歌上搜索过。我不知道如何简洁地表达这个问题。

作为学习项目,我正在尝试创建一个简单的 html 编辑工具,其中包括一个侧面板,您可以在其中编辑每个布局元素的不同属性,就像 Figma 中一样。问题是,在所述面板中,当我选择不同的元素时,输入值不会更新。

enter image description here

目标对象中的值按照计划很好地更改,但问题是当我从一个对象更改为另一个对象时,输入值仍然存在。

我在这里创建了一个隔离问题的演示https://codesandbox.io/p/sandbox/react-question-example-3qlyp5(也在下面)。在这里,我可以在两个对象中进行选择,并通过编辑输入来正确更改所述对象的“x”字段。但是,当我选择其他对象时,输入值不会更新以显示新对象字段的值。只有第一个选择才能正确更新字段值。

我很想删除输入并立即再次显示它,以重新实例化它,但这是次优的。因为这是一个学习项目,所以我最好问一下。

import "./styles.css";
import { useState } from "react";

const exampleThings = [
  {
    x: "12px",
    i: 0,
    a: "foo",
  },
  {
    x: "5px",
    i: 1,
    a: "bar",
  },
];

const positionParse = (pos) => {
  const parsed = parseFloat(pos);
  if (isNaN(parsed)) throw new Error("oops");
  return parsed;
};

function PositionEditor({ setPositionDef, positionDef }) {
  const [hasError, setHasError] = useState(false);
  const [value, setValue] = useState(positionDef);

  const changed = (e) => {
    setValue(e.target.value);
    try {
      positionDef = positionParse(e.target.value);
      setHasError(false);
      setPositionDef(e.target.value);
    } catch (e) {
      setHasError(true);
    }
  };

  return (
    <input
      type="text"
      value={value}
      onChange={changed}
      style={{ borderColor: hasError ? "red" : "unset" }}
    />
  );
}

function ThingSelector({ select, t }) {
  return <button onClick={select}>Select thing {t} </button>;
}

export default function App() {
  const [things, setThings] = useState([...exampleThings]);
  const [selectedThing, setSelectedThing] = useState(undefined);
  const selectThing = (i) => {
    const thingIndex = things.findIndex((thing) => thing.i === i);
    console.log("select thing", thingIndex);
    setSelectedThing(things[thingIndex]);
  };
  const editThingPositionDef = (position) => {
    const selectedThingId = things.findIndex((t) => t.i === selectedThing.i);
    const newThings = [...things];
    const newSelectedThing = {
      ...selectedThing,
      x: position,
    };

    newThings[selectedThingId] = {
      position,
      ...newSelectedThing,
    };
    setThings(newThings);
    setSelectedThing(newSelectedThing);
  };
  return (
    <div className="App">
      {things.map((thing) => {
        return (
          <ThingSelector
            select={(e) => selectThing(thing.i)}
            t={thing.a}
            key={thing.i}
          />
        );
      })}

      {selectedThing === undefined ? (
        <p>Select something</p>
      ) : (
        <>
          <p>
            Editing: {selectedThing.a}. My x is {positionParse(selectedThing.x)}
          </p>
          <PositionEditor
            setPositionDef={editThingPositionDef}
            positionDef={selectedThing.x}
          />
        </>
      )}
    </div>
  );
}
reactjs input
1个回答
0
投票

好的!有趣的是,ChatGpt 给了我一个有用的答案!

我需要的是一个新的 useEffect 钩子 - 这就是为什么我需要一个真实的项目来了解钩子的使用。

这里是固定代码(唯一的变化是添加了 useEffect 钩子)

import "./styles.css";
import { useState, useEffect } from "react";

const exampleThings = [
  {
    x: "12px",
    i: 0,
    a: "foo",
  },
  {
    x: "5px",
    i: 1,
    a: "bar",
  },
];

const positionParse = (pos) => {
  const parsed = parseFloat(pos);
  if (isNaN(parsed)) throw new Error("oops");
  return parsed;
};

function PositionEditor({ setPositionDef, positionDef }) {
  const [hasError, setHasError] = useState(false);
  const [value, setValue] = useState(positionDef);

  useEffect(() => {
    setValue(positionDef);
  }, [positionDef]);

  const changed = (e) => {
    setValue(e.target.value);
    try {
      positionDef = positionParse(e.target.value);
      setHasError(false);
      setPositionDef(e.target.value);
    } catch (e) {
      setHasError(true);
    }
  };

  return (
    <input
      type="text"
      value={value}
      onChange={changed}
      style={{ borderColor: hasError ? "red" : "unset" }}
    />
  );
}

function ThingSelector({ select, t }) {
  return <button onClick={select}>Select thing {t} </button>;
}

export default function App() {
  const [things, setThings] = useState([...exampleThings]);
  const [selectedThing, setSelectedThing] = useState(undefined);
  const selectThing = (i) => {
    const thingIndex = things.findIndex((thing) => thing.i === i);
    console.log("select thing", thingIndex);
    setSelectedThing(things[thingIndex]);
  };
  const editThingPositionDef = (position) => {
    const selectedThingId = things.findIndex((t) => t.i === selectedThing.i);
    const newThings = [...things];
    const newSelectedThing = {
      ...selectedThing,
      x: position,
    };

    newThings[selectedThingId] = {
      position,
      ...newSelectedThing,
    };
    setThings(newThings);
    setSelectedThing(newSelectedThing);
  };
  return (
    <div className="App">
      {things.map((thing) => {
        return (
          <ThingSelector
            select={(e) => selectThing(thing.i)}
            t={thing.a}
            key={thing.i}
          />
        );
      })}

      {selectedThing === undefined ? (
        <p>Select something</p>
      ) : (
        <>
          <p>
            Editing: {selectedThing.a}. My x is {positionParse(selectedThing.x)}
          </p>
          <PositionEditor
            setPositionDef={editThingPositionDef}
            positionDef={selectedThing.x}
          />
        </>
      )}
    </div>
  );
}

© www.soinside.com 2019 - 2024. All rights reserved.