如何触发用户在 React 中输入的数据呈现?
How to trigger of the render of data that a user inputs in React?
在此应用程序中,学生数据是从 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 重新渲染标签,但到目前为止都没有成功......
谢谢!
好的,因为你如何使用本地状态设置新标签,然后将道具传递给标签,导致同步错误,因为反应状态都是异步的。
所以我将代码更新为 useRef 以获取当前值,它应该可以工作。
有很多地方需要改变。基本上你的代码都搞砸了,因为你正在用另一个状态更新状态。 (例如,你用新标签更新标签),但 newtags 还没有用新值更新。
我还在 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()
};
然后将此行更改为更新后的行。
{student?.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
在此应用程序中,学生数据是从 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 重新渲染标签,但到目前为止都没有成功......
谢谢!
好的,因为你如何使用本地状态设置新标签,然后将道具传递给标签,导致同步错误,因为反应状态都是异步的。
所以我将代码更新为 useRef 以获取当前值,它应该可以工作。
有很多地方需要改变。基本上你的代码都搞砸了,因为你正在用另一个状态更新状态。 (例如,你用新标签更新标签),但 newtags 还没有用新值更新。
我还在 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()
};
然后将此行更改为更新后的行。
{student?.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