Material UI value prop 在值状态随着组件的动态渲染而改变后不更新
MaterialUI value prop not updating after value state change with dynamic rending of components
我正在动态生成 material ui 表单组件,我想在写入表单时更新它们的值。然而,value prop 被分配给一个 useState values 对象。当我更改此对象并更新状态时,对象中的值会正确更改,但 material UI 组件不会,因为它的值与原始值对象相关联。我相信这与我正在使用按钮动态创建这些组件这一事实有关。
文本字段中的值属性未更新。
我正在更新 handleAnswersChange 中这些字段的值。它检查答案是否已经存在。如果是这样,它将更新它。如果没有,它将创建一个新的。
interface State {
title: string;
question: string;
answers: Array<Answer>;
correctAnswer: number;
}
interface Answer {
answer: string;
id: number;
}
export default function CreateQuestion() {
const [answers, setAnswers] = React.useState<Array<JSX.Element>>([]);
const [errorAnswer, setErrorAnswer] = React.useState(false);
const [values, setValues] = React.useState<State>({
title: "",
question: "",
answers: [{ answer: "", id: 1 }],
correctAnswer: 1,
});
useEffect(() => {
console.log(values);
}, [values]);
const handleChange =
(prop: any) => (event: React.ChangeEvent<HTMLInputElement>) => {
setValues({ ...values, [prop]: event.target.value });
};
const handleAnswersChange = (
prop: any,
id: number
) => (event: React.ChangeEvent<HTMLInputElement>) => {
console.log(values.answers[0].answer);
let answerIndex: number = 0;
let doesExist: boolean = false;
values.answers.map((answer, index) => {
if (answer.id === id) {
answerIndex = index;
doesExist = true;
}
});
if (doesExist) {
const tempValues = values.answers;
tempValues[answerIndex] = {
answer: tempValues[answerIndex].answer + event.target.value,
id: id,
};
setValues({
...values,
[prop]: [...tempValues],
});
} else {
setValues({
...values,
[prop]: [...values.answers, { answer: event.target.value, id: id }],
});
}
};
const createAnswer = () => {
const array = [...answers];
array.push(
<Box sx={{ m: 1 }} key={answers.length}>
<FormControl
sx={{ width: "60ch" }}
variant="outlined"
key={answers.length}
>
<TextField
id="outlined-required"
key={answers.length}
label={"Answer " + (answers.length + 1)}
value={values.answers[answers.length - 1].answer}
onChange={
handleAnswersChange("answers", values.answers.length);
}
/>
</FormControl>
</Box>
您使用了错误的索引。你在它上面映射,也有你相同的静态索引。所以formik会把它放错地方。
handleAnswersChange(event, "answers", values.answers.length);
这总是 select 错误的索引。由于第一个元素的 values.answers.length
为 1,但其索引为 0。
尝试使用 .map 和像 this 这样的索引。
自己保存答案,然后用地图渲染它们。
你也不需要那么多钥匙。仅针对 map 的直接子节点。
更新:
我刚刚看到您已经将答案也保存在值中,因此您可以简单地映射 values.answers
并丢弃答案数组。
我正在动态生成 material ui 表单组件,我想在写入表单时更新它们的值。然而,value prop 被分配给一个 useState values 对象。当我更改此对象并更新状态时,对象中的值会正确更改,但 material UI 组件不会,因为它的值与原始值对象相关联。我相信这与我正在使用按钮动态创建这些组件这一事实有关。
文本字段中的值属性未更新。
我正在更新 handleAnswersChange 中这些字段的值。它检查答案是否已经存在。如果是这样,它将更新它。如果没有,它将创建一个新的。
interface State {
title: string;
question: string;
answers: Array<Answer>;
correctAnswer: number;
}
interface Answer {
answer: string;
id: number;
}
export default function CreateQuestion() {
const [answers, setAnswers] = React.useState<Array<JSX.Element>>([]);
const [errorAnswer, setErrorAnswer] = React.useState(false);
const [values, setValues] = React.useState<State>({
title: "",
question: "",
answers: [{ answer: "", id: 1 }],
correctAnswer: 1,
});
useEffect(() => {
console.log(values);
}, [values]);
const handleChange =
(prop: any) => (event: React.ChangeEvent<HTMLInputElement>) => {
setValues({ ...values, [prop]: event.target.value });
};
const handleAnswersChange = (
prop: any,
id: number
) => (event: React.ChangeEvent<HTMLInputElement>) => {
console.log(values.answers[0].answer);
let answerIndex: number = 0;
let doesExist: boolean = false;
values.answers.map((answer, index) => {
if (answer.id === id) {
answerIndex = index;
doesExist = true;
}
});
if (doesExist) {
const tempValues = values.answers;
tempValues[answerIndex] = {
answer: tempValues[answerIndex].answer + event.target.value,
id: id,
};
setValues({
...values,
[prop]: [...tempValues],
});
} else {
setValues({
...values,
[prop]: [...values.answers, { answer: event.target.value, id: id }],
});
}
};
const createAnswer = () => {
const array = [...answers];
array.push(
<Box sx={{ m: 1 }} key={answers.length}>
<FormControl
sx={{ width: "60ch" }}
variant="outlined"
key={answers.length}
>
<TextField
id="outlined-required"
key={answers.length}
label={"Answer " + (answers.length + 1)}
value={values.answers[answers.length - 1].answer}
onChange={
handleAnswersChange("answers", values.answers.length);
}
/>
</FormControl>
</Box>
您使用了错误的索引。你在它上面映射,也有你相同的静态索引。所以formik会把它放错地方。
handleAnswersChange(event, "answers", values.answers.length);
这总是 select 错误的索引。由于第一个元素的 values.answers.length
为 1,但其索引为 0。
尝试使用 .map 和像 this 这样的索引。
自己保存答案,然后用地图渲染它们。
你也不需要那么多钥匙。仅针对 map 的直接子节点。
更新:
我刚刚看到您已经将答案也保存在值中,因此您可以简单地映射 values.answers
并丢弃答案数组。