【问题标题】:How to trigger of the render of data that a user inputs in React?如何触发用户在 React 中输入的数据的呈现?
【发布时间】:2020-12-14 22:14:50
【问题描述】:

在这个应用程序中,学生数据是从 API 中提取的,可以通过点击卡片上的加号按钮为每个学生添加新标签。

问题:标签在输入后不会立即呈现在屏幕上。它们只会在下拉菜单关闭并再次打开或连续输入多个标签后呈现。

项目和代码可以在这里找到: https://codesandbox.io/s/hatch-frontend-mch-52n67?file=/src/components/views/Card.js:2280-2320

Card.js

// ...

// Submit Handler function:
const submitNewTagHandler = (e) => {
    e.preventDefault();
    setHasTags(true);
    console.log(tags);
    setHeightState(
       `${content.current.scrollHeight}px`
    );
    setTags([...tags, newTag]);
    updateStudents(tags, index);
    setNewTag('');
  };


//Tag render:
{hasTags && <Tags student={student} />}
// Tag input:
<form onSubmit={submitNewTagHandler}>
    <input
    className='​add-tag-input​'
    onChange={(e) => setNewTag(e.target.value)}
    value={newTag}
    type='text'
    placeholder='Add a new tag'
    />
</form>

App.js

// updateStudent is called as update in App.js
// (This updates the main data array called students)
const update = (t, index) => {
    setTags(t);
    setStudents(
      students.map((student, i) => {
        // console.log(i, index);
        if (i === index) {
          console.log(student, tags);
          return { ...student, tags };
        } else {
          return student;
        }
      })
    );
    console.log(students);
  };

Tags.js

const Tags = (props) => {
  return (
    <div className='tags'>
      {props.student.tags.map((tag, index) => {
        return (
          <h3 className='tag' key={index}>
            {tag}{' '}
          </h3>
        );
      })}
    </div>
  );
};

我尝试了不同的方法来使用 useEffect 重新渲染标签,但到目前为止都没有成功……

谢谢!

【问题讨论】:

  • 好的np!我会添加一些代码!
  • 您的 组件是生成列表的组件吗?您的标签道具在哪里传递?你说的下拉列表的组件在哪里。
  • 组件树是这样的:App.js > DisplayStudentInfo.js > Card.js > Tags.js
  • 如果您不介意,既然您正在寻求帮助解决问题,请更好地标记代码,例如您共享的每个代码的组件名称。
  • 代码看起来不错,但我们必须看看您正在渲染的组件是什么。这可能是由于您没有正确传递道具等造成的,如果您不想共享代码,那么我们的帮助将受到限制。

标签: javascript reactjs input render


【解决方案1】:

好的,因为您使用本地状态 setNewTags,然后将道具传递给标签,导致同步错误,因为反应状态都是异步的。

所以我将代码更新为 useRef 以获取当前值,它应该可以工作。

需要进行许多更改。基本上你的代码都搞砸了,因为你正在用另一个状态更新状态。 (例如,你用新标签更新标签),但新标签尚未更新为新值。

我还删除了您在 App.js 中的 useEffect,并向您展示了如何改用 useMemo。

删除这两行

  const [tags, setTags] = useState(student.tags);
  const [newTag, setNewTag] = useState('');

创建新的输入参考

  const inputRef = useRef()
  const formRef = useRef()

更改输入

       <input
          className='​add-tag-input​'
          ref = {inputRef} //add this
          //value={newTag} remove this
          type='text'
          placeholder='Add a new tag'
        />

然后你的句柄提交函数

  const submitNewTagHandler = (e) => {
    const value = inputRef.current.value
    e.preventDefault();
    setHeightState(
       `${content.current.scrollHeight}px`
    );
    updateStudents([...student.tags, value], index);
    formRef.current.reset()
  };

然后将此行更改为更新的行。

{学生?.tags?.length > 0 && }

然后你需要用一个键更新你的 .map 否则它不能正确渲染。

<Card key={`student-${student.id}`} students={props.students} student={student} index={index} updateStudents={props.updateStudents} />

在你的更新函数中

const update = (t, index) => {
    setTags(t);
    setStudents((prev) =>
      prev.map((student, i) => {
        // console.log(i, index);
        if (i === index) {
          console.log("prev map", student, t);
          return { ...student, tags: t };
        } else {
          return student;
        }
      })
    );
    console.log(students);
  };

更新组件到这个

const Tags = ({ tags }) => {
  return (
    <div className="tags">
      {tags.map((tag, index) => {
        return (
          <h3 className="tag" key={`tag-${index}`}>
            {tag}{" "}
          </h3>
        );
      })}
    </div>
  );
};

添加这个来修复你的手风琴输入被隐藏的地方。

 useEffect(() => {

    if (setActive) setHeightState(`${content.current.scrollHeight}px`);

  },[props])

改动太多了。我可能在这里错过了其中一些。 see new sandbox

【讨论】:

  • 你的输入框并没有消失,它只是因为你的手风琴 css 而被隐藏了 -> 溢出:隐藏;
  • 首先,非常感谢!
  • 几个问题... 1) {student?.tags?.length &gt; 0 &amp;&amp; } 为什么放?在学生和标签之后?
  • 2) .filter( ({ tags }) =&gt; tagFilter === "" || tags.filter((x) =&gt; x.match(new RegExp(tagFilter, "i"))).length &gt; ); -- 为什么使用tagFilter === "" ||new RegExp 从 tagFilter 中创建一个正则表达式,然后 match 创建一个匹配的标签数组,对吗?
  • student?.tag?.length 用于防止在第一次渲染期间未定义 student 或 student.tags 时引发错误。
猜你喜欢
  • 1970-01-01
  • 2020-05-21
  • 1970-01-01
  • 1970-01-01
  • 2021-07-27
  • 1970-01-01
  • 1970-01-01
  • 2021-04-01
  • 1970-01-01
相关资源
最近更新 更多