Textfield 在 table ReactJs 中无法正常工作
Textfield not working properly inside a table ReactJs
我有一个包含对象数组的对象
initialPreconfigTodoState = {
todos: [
{
title: 'title1',
dueDate: new Date(),
create: true,
assignedTo: 'role',
},
{
title: 'title2',
dueDate: new Date(),
create: true,
assignedTo: 'role',
}]
};
我使用这个对象数组来控制 table
中文本字段的状态
const [preconfig, setPreconfig] = useState(initialPreconfigTodoState);
{preconfig.todos.map((todo, index) => {
return (
<TableRow
className="h-64 cursor-pointer"
key={Math.random()}
>
<TableCell className="th" component="th" scope="row">
<TextField
id={`titleForm${index}`}
name={`titleForm${index}`}
onChange={(event) => handleTitle(event, index)}
value={todo.title}
type="text"
variant="outlined"
required={todo.create ? true : false}
fullWidth
/>
</TableCell>
当我尝试在文本字段中输入时,我不知道会发生什么,但我需要为我输入的每个字符单击文本字段,我认为是 useState 钩子在重新呈现组件时导致了这个问题我找不到解决方案。
这是我在 onChange 回调上的句柄函数,
const handleTitle = (event, index) => {
let newArray = [...preconfig.todos];
newArray[index] = {
...newArray[index],
title: event.target.value,
};
setPreconfig({ todos: newArray });
};
这里是完整的代码
const initialPreconfigTodoState = {
todos: [
{
title: "title1",
dueDate: new Date(),
create: true,
assignedTo: "Role"
},
{
title: "title2",
dueDate: new Date(),
create: true,
assignedTo: "Role"
}
]
};
function TodoDialog() {
const [preconfig, setPreconfig] =
useState(initialPreconfigTodoState);
const handleTitle = (event, index) => {
let newArray = [...preconfig.todos];
newArray[index] = {
...newArray[index],
title: event.target.value
};
setPreconfig({ todos: newArray });
};
return (
<div>
<Dialog open={true} maxWidth="xl" scroll="paper">
<DialogContent>
<div>
<Table aria-labelledby="tableTitle">
<TableBody>
<TableRow className="h-64 cursor-pointer" key=.
{Math.random()}>
<TableCell className="th" component="th" scope="row">
Title
</TableCell>
<TableCell className="th" component="th" scope="row">
Due Date
</TableCell>
<TableCell className="th" component="th" scope="row">
Asigned To
</TableCell>
<TableCell className="th" component="th" scope="row">
Create
</TableCell>
</TableRow>
{preconfig.todos.map((todo, index) => {
return (
<TableRow
className="h-64 cursor-pointer"
key={Math.random()}
>
<TableCell className="th" component="th" scope="row">
<TextField
id={`titleForm${index}`}
name={`titleForm${index}`}
onChange={(event) => handleTitle(event, index)}
value={todo.title}
type="text"
variant="outlined"
required={todo.create ? true : false}
fullWidth
/>
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</div>
</DialogContent>
<DialogActions>
<Button color="primary" variant="contained">
Cancel
</Button>
<Button type="submit" color="primary" variant="contained" autoFocus>
Save
</Button>
</DialogActions>
</Dialog>
</div>
);
}
确实是thenuseState
引起的问题。您的整个表单(我想它是某种形式)更改了它在 render
中映射的数组。难怪整个表格re-renders.
显而易见的解决方案是存储输入值(例如在状态中)并仅在提交时更新原始数组(通过 setPreconfig
)。
那是因为 TableRow 上的 key={Math.random()}
。
将其更改为 key={index}
应该可以。
在 Math.random()
中,您的键会更改每次渲染,并且 React 会失去其引用。
我有一个包含对象数组的对象
initialPreconfigTodoState = {
todos: [
{
title: 'title1',
dueDate: new Date(),
create: true,
assignedTo: 'role',
},
{
title: 'title2',
dueDate: new Date(),
create: true,
assignedTo: 'role',
}]
};
我使用这个对象数组来控制 table
中文本字段的状态const [preconfig, setPreconfig] = useState(initialPreconfigTodoState);
{preconfig.todos.map((todo, index) => {
return (
<TableRow
className="h-64 cursor-pointer"
key={Math.random()}
>
<TableCell className="th" component="th" scope="row">
<TextField
id={`titleForm${index}`}
name={`titleForm${index}`}
onChange={(event) => handleTitle(event, index)}
value={todo.title}
type="text"
variant="outlined"
required={todo.create ? true : false}
fullWidth
/>
</TableCell>
当我尝试在文本字段中输入时,我不知道会发生什么,但我需要为我输入的每个字符单击文本字段,我认为是 useState 钩子在重新呈现组件时导致了这个问题我找不到解决方案。
这是我在 onChange 回调上的句柄函数,
const handleTitle = (event, index) => {
let newArray = [...preconfig.todos];
newArray[index] = {
...newArray[index],
title: event.target.value,
};
setPreconfig({ todos: newArray });
};
这里是完整的代码
const initialPreconfigTodoState = {
todos: [
{
title: "title1",
dueDate: new Date(),
create: true,
assignedTo: "Role"
},
{
title: "title2",
dueDate: new Date(),
create: true,
assignedTo: "Role"
}
]
};
function TodoDialog() {
const [preconfig, setPreconfig] =
useState(initialPreconfigTodoState);
const handleTitle = (event, index) => {
let newArray = [...preconfig.todos];
newArray[index] = {
...newArray[index],
title: event.target.value
};
setPreconfig({ todos: newArray });
};
return (
<div>
<Dialog open={true} maxWidth="xl" scroll="paper">
<DialogContent>
<div>
<Table aria-labelledby="tableTitle">
<TableBody>
<TableRow className="h-64 cursor-pointer" key=.
{Math.random()}>
<TableCell className="th" component="th" scope="row">
Title
</TableCell>
<TableCell className="th" component="th" scope="row">
Due Date
</TableCell>
<TableCell className="th" component="th" scope="row">
Asigned To
</TableCell>
<TableCell className="th" component="th" scope="row">
Create
</TableCell>
</TableRow>
{preconfig.todos.map((todo, index) => {
return (
<TableRow
className="h-64 cursor-pointer"
key={Math.random()}
>
<TableCell className="th" component="th" scope="row">
<TextField
id={`titleForm${index}`}
name={`titleForm${index}`}
onChange={(event) => handleTitle(event, index)}
value={todo.title}
type="text"
variant="outlined"
required={todo.create ? true : false}
fullWidth
/>
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</div>
</DialogContent>
<DialogActions>
<Button color="primary" variant="contained">
Cancel
</Button>
<Button type="submit" color="primary" variant="contained" autoFocus>
Save
</Button>
</DialogActions>
</Dialog>
</div>
);
}
确实是thenuseState
引起的问题。您的整个表单(我想它是某种形式)更改了它在 render
中映射的数组。难怪整个表格re-renders.
显而易见的解决方案是存储输入值(例如在状态中)并仅在提交时更新原始数组(通过 setPreconfig
)。
那是因为 TableRow 上的 key={Math.random()}
。
将其更改为 key={index}
应该可以。
在 Math.random()
中,您的键会更改每次渲染,并且 React 会失去其引用。