Reactjs 反应:更改深度嵌套状态优化
我提出了一个解决方案,可以在React中的第二级嵌套状态中更改属性,该状态不可伸缩,而且似乎效率不高。如何重构Reactjs 反应:更改深度嵌套状态优化,reactjs,state,immutability,nested-datalist,Reactjs,State,Immutability,Nested Datalist,我提出了一个解决方案,可以在React中的第二级嵌套状态中更改属性,该状态不可伸缩,而且似乎效率不高。如何重构handleOnChange方法以更改reps和weight import React,{useState}来自“React”; 常量训练={ id:“123-234sdf-1213”, 名称:“工单名称”, 完成:错误, 练习:[ { 名称:“后蹲”, 设置:[ { 编号:0, 代表:0,, 重量:0,, 完成:错误, }, { 编号:1, 代表:0,, 重量:0,, 完成:错误, }
handleOnChange
方法以更改reps
和weight
import React,{useState}来自“React”;
常量训练={
id:“123-234sdf-1213”,
名称:“工单名称”,
完成:错误,
练习:[
{
名称:“后蹲”,
设置:[
{
编号:0,
代表:0,,
重量:0,,
完成:错误,
},
{
编号:1,
代表:0,,
重量:0,,
完成:错误,
},
{
编号:2,
代表:0,,
重量:0,,
完成:错误,
},
],
},
{
名称:“腿部按压”,
设置:[
{
编号:0,
代表:0,,
重量:0,,
完成:错误,
},
{
编号:1,
代表:0,,
重量:0,,
完成:错误,
},
{
编号:2,
代表:0,,
重量:0,,
完成:错误,
},
],
},
],
};
导出默认函数App(){
const[workoutState,setWorkoutState]=使用状态(训练);
常量handleOnChange=(e,exIndex,setIndex)=>{
const value=e.target.value?parseFloat(e.target.value):“”;
const exercises=[…workoutState.exercises];
练习[exIndex]。设置[setIndex]={
…练习[exIndex]。设置[setIndex],
[e.target.name]:值,
};
设置工作状态({
…美国,
练习,
});
};
返回(
{workoutState.name}
{workoutState.exercises.map((ex,exIndex)=>(
{ex.name}
{ex.sets.map((set,setIndex)=>(
代表:{'}
handleOnChange(e,exIndex,setIndex)}
/>
重量:{'}
handleOnChange(e,exIndex,setIndex)}
/>
))}
))}
);
}
我想说,您希望如何更新嵌套状态,这是正确的,但您当前的handleOnChange
实现中确实存在状态变异。您正在变异练习[exIndex]
const handleOnChange = (e, exIndex, setIndex) => {
const value = e.target.value ? parseFloat(e.target.value) : "";
const exercises = [...workoutState.exercises];
exercises[exIndex].sets[setIndex] = { // <-- mutates exercises[exIndex]
...exercises[exIndex].sets[setIndex],
[e.target.name]: value,
};
setWorkoutState({
...workoutState,
exercises,
});
};
输入。我添加了一个step
属性并附加了curried处理程序。我还将每个输入放在标签
元素中以便于访问;可以单击标签并聚焦该字段
<div>
<label>
reps:{" "}
<input
value={set.reps}
name="reps"
step={1}
type="number"
onChange={handleOnChange(exIndex, setIndex)}
/>
</label>
</div>
<div>
<label>
weight:{" "}
<input
value={set.weight}
name="weight"
step={0.1}
type="number"
onChange={handleOnChange(exIndex, setIndex)}
/>
</label>
</div>
代表:{'}
重量:{'}
完整代码:
const workout = {
id: "123-234sdf-1213",
name: "wo name",
done: false,
exercises: [
{
name: "back squat",
sets: [
{
number: 0,
reps: 0,
weight: 0,
done: false
},
{
number: 1,
reps: 0,
weight: 0,
done: false
},
{
number: 2,
reps: 0,
weight: 0,
done: false
}
]
},
{
name: "leg press",
sets: [
{
number: 0,
reps: 0,
weight: 0,
done: false
},
{
number: 1,
reps: 0,
weight: 0,
done: false
},
{
number: 2,
reps: 0,
weight: 0,
done: false
}
]
}
]
};
export default function App() {
const [workoutState, setWorkoutState] = useState(workout);
const handleOnChange = (eIndex, sIndex) => (e) => {
const { name, value } = e.target;
setWorkoutState((workoutState) => ({
...workoutState,
exercises: workoutState.exercises.map((exercise, exerciseIndex) =>
exerciseIndex === eIndex
? {
...exercise,
sets: exercise.sets.map((set, setIndex) =>
setIndex === sIndex
? {
...set,
[name]: Number(value)
}
: set
)
}
: exercise
)
}));
};
return (
<div className="App">
<h1>{workoutState.name}</h1>
{workoutState.exercises.map((ex, exIndex) => (
<>
<h2>{ex.name}</h2>
{ex.sets.map((set, setIndex) => (
<div key={`${ex.name}_${setIndex}`}>
<h3>Set {setIndex}</h3>
<div>
<label>
reps:{" "}
<input
value={set.reps}
name="reps"
step={1}
type="number"
onChange={handleOnChange(exIndex, setIndex)}
/>
</label>
</div>
<div>
<label>
weight:{" "}
<input
value={set.weight}
name="weight"
step={0.1}
type="number"
onChange={handleOnChange(exIndex, setIndex)}
/>
</label>
</div>
</div>
))}
</>
))}
</div>
);
}
const锻炼={
id:“123-234sdf-1213”,
名称:“工单名称”,
完成:错误,
练习:[
{
名称:“后蹲”,
设置:[
{
编号:0,
代表:0,,
重量:0,,
完成:错误
},
{
编号:1,
代表:0,,
重量:0,,
完成:错误
},
{
编号:2,
代表:0,,
重量:0,,
完成:错误
}
]
},
{
名称:“腿部按压”,
设置:[
{
编号:0,
代表:0,,
重量:0,,
完成:错误
},
{
编号:1,
代表:0,,
重量:0,,
完成:错误
},
{
编号:2,
代表:0,,
重量:0,,
完成:错误
}
]
}
]
};
导出默认函数App(){
const[workoutState,setWorkoutState]=使用状态(训练);
常数变化=(eIndex,sIndex)=>(e)=>{
常量{name,value}=e.target;
setWorkoutState((workoutState)=>({
…美国,
练习:workoutState.exercises.map((练习,练习索引)=>
exerciseIndex==eIndex
? {
运动
集合:exercise.sets.map((集合,集合索引)=>
setIndex==sIndex
? {
设置
[名称]:编号(值)
}
:设置
)
}
:练习
)
}));
};
返回(
{workoutState.name}
{workoutState.exercises.map((ex,exIndex)=>(
{ex.name}
{ex.sets.map((set,setIndex)=>(
集合{setIndex}
代表:{'}
重量:{'}
))}
))}
);
}
但我似乎无法删除de first 0Hi@DavideCariani您能否澄清一下您“无法删除[the]”的意思第一个0?你指的是你的训练中的默认重复次数/重量值吗?练习
数组?嘿@DrewReese,是的,我的意思是不可能删除第一个0。在沙箱中你可以看到它。@DavideCariani啊,好的,如果你将[名称]:数字(值)
更改为[名称]:value
您可以在输入中将空格从“0”返回到空字符串。
const workout = {
id: "123-234sdf-1213",
name: "wo name",
done: false,
exercises: [
{
name: "back squat",
sets: [
{
number: 0,
reps: 0,
weight: 0,
done: false
},
{
number: 1,
reps: 0,
weight: 0,
done: false
},
{
number: 2,
reps: 0,
weight: 0,
done: false
}
]
},
{
name: "leg press",
sets: [
{
number: 0,
reps: 0,
weight: 0,
done: false
},
{
number: 1,
reps: 0,
weight: 0,
done: false
},
{
number: 2,
reps: 0,
weight: 0,
done: false
}
]
}
]
};
export default function App() {
const [workoutState, setWorkoutState] = useState(workout);
const handleOnChange = (eIndex, sIndex) => (e) => {
const { name, value } = e.target;
setWorkoutState((workoutState) => ({
...workoutState,
exercises: workoutState.exercises.map((exercise, exerciseIndex) =>
exerciseIndex === eIndex
? {
...exercise,
sets: exercise.sets.map((set, setIndex) =>
setIndex === sIndex
? {
...set,
[name]: Number(value)
}
: set
)
}
: exercise
)
}));
};
return (
<div className="App">
<h1>{workoutState.name}</h1>
{workoutState.exercises.map((ex, exIndex) => (
<>
<h2>{ex.name}</h2>
{ex.sets.map((set, setIndex) => (
<div key={`${ex.name}_${setIndex}`}>
<h3>Set {setIndex}</h3>
<div>
<label>
reps:{" "}
<input
value={set.reps}
name="reps"
step={1}
type="number"
onChange={handleOnChange(exIndex, setIndex)}
/>
</label>
</div>
<div>
<label>
weight:{" "}
<input
value={set.weight}
name="weight"
step={0.1}
type="number"
onChange={handleOnChange(exIndex, setIndex)}
/>
</label>
</div>
</div>
))}
</>
))}
</div>
);
}