Formik & Mobx 从 API 设置初始值
Formik & Mobx setting initial values from API
首先请允许我说我是 React 新手,我已经看过其他帖子,但我仍然无法解决问题。
我的问题如下,我正在尝试创建一个表格,允许用户为锻炼中的每项锻炼输入他们的代表、组数和使用的重量。但是,如果用户尝试输入任何内容,它就像一个只读字段。我怀疑我设置初始值的方式有问题。在我的 WorkoutStore.ts 中,我定义了一个名为 exercisesForForm 的计算值,如下所示:
@computed get exercisesForForm() {
const data = this.exercises.map((e) => ({
name: e.name,
id: e.id,
sets: e.sets,
reps: e.reps,
weight: e.weight
}));
return data;
}
当我控制台记录它时,我可以清楚地看到它正在正确设置。但是,如果我尝试访问它或任何东西,它会一直抱怨它未定义。所以真正的主要问题是:定义从 API 端点接收的初始值的正确方法是什么。如果这只是一个专门针对一个实体的表单(比如一个练习),那么这会容易得多,因为它将是一个简单的 1:1 数据到表单中元素的映射
我正在尝试按如下方式定义我的表单:
const rootStore = useContext(RootStoreContext);
const {getExercises, exercises, exercisesForForm} = rootStore.workoutStore;
useEffect(() => {
if(match.params.workoutId) {
getExercises(match.params.workoutId);
}
}, [getExercises, match.params.workoutId])
<Formik key={uuid()} onSubmit={handleFormSubmit} initialValues={exercisesForForm} enableReinitialize={true}>
{({
handleSubmit,
handleChange,
values
}) => (
<Form onSubmit={handleSubmit}>
{exercises.map((exercise, index) =>
(
<Fragment key={exercise.id}>
<Header>{exercise.name}</Header>
<Form.Row>
<Form.Group as={Col}>
<Form.Label>Sets</Form.Label>
<Form.Control key={uuid()} type="number" name='sets' value={0} onChange={handleChange}/>
</Form.Group>
</Form.Row>
<Form.Row>
<Form.Group as={Col}>
<Form.Label>Reps</Form.Label>
<Form.Control key={uuid()} type="number" name='reps' onChange={handleChange}/>
</Form.Group>
</Form.Row>
<Form.Row>
<Form.Group as={Col}>
<Form.Label>Weight</Form.Label>
<Form.Control key={uuid()} type="number" name='weight' onChange={handleChange}/>
</Form.Group>
</Form.Row>
</Fragment>
)
)}
<Form.Row>
<Form.Group as={Col} controlId='04'>
<Button content="Submit" floated='right' type="submit"/>
</Form.Group>
</Form.Row>
</Form>
)}</Formik>
对此的后续问题是,如何正确定义表单的名称组件?在 MVC.NET 中(这是我最熟悉的网络方式)我会简单地定义一个数组并使用 @Html.TextBoxFor(x => x.Answers[i].Answer, new { type = "text" })
之类的东西动态创建输入
经过多次谷歌搜索、实验和重新阅读文档后,我终于弄明白了。我将代码更改为如下所示:
<Formik key={uuid()} onSubmit={handleFormSubmit} enableReinitialize={true} initialValues={exercisesForForm}
render={({values, handleChange, handleSubmit}) => (
<Form onSubmit={handleSubmit}>
{values.map((e, index) => (
<Fragment key={index}>
<Header>{e.name}</Header>
<Form.Row>
<Form.Group as={Col}>
<Form.Label>Sets</Form.Label>
<Form.Control key={`${index}_sets`} type='number' name={`[${index}].sets`} value={(e.sets)} onChange={handleChange} />
</Form.Group>
</Form.Row>
<Form.Row>
<Form.Group as={Col}>
<Form.Label>Reps</Form.Label>
<Form.Control key={`${index}_reps`} type='number' name={`[${index}].reps`} value={(e.reps)} onChange={handleChange} />
</Form.Group>
</Form.Row>
<Form.Row>
<Form.Group as={Col}>
<Form.Label>Weight</Form.Label>
<Form.Control key={`${index}_weight`} type='number' name={`[${index}].weight`} value={(e.weight)} onChange={handleChange} />
</Form.Group>
</Form.Row>
</Fragment>
)
)}
)}
<Form.Row>
<Form.Group as={Col} controlId='04'>
<Button content="Submit" floated='right' type="submit"/>
</Form.Group>
</Form.Row>
</Form>
)}
/>
有几点需要注意:我正在使用 values
属性 来访问初始值;我还使用索引来设置字段的名称。我认为是缺失的 link 将它们联系在一起。
首先请允许我说我是 React 新手,我已经看过其他帖子,但我仍然无法解决问题。
我的问题如下,我正在尝试创建一个表格,允许用户为锻炼中的每项锻炼输入他们的代表、组数和使用的重量。但是,如果用户尝试输入任何内容,它就像一个只读字段。我怀疑我设置初始值的方式有问题。在我的 WorkoutStore.ts 中,我定义了一个名为 exercisesForForm 的计算值,如下所示:
@computed get exercisesForForm() {
const data = this.exercises.map((e) => ({
name: e.name,
id: e.id,
sets: e.sets,
reps: e.reps,
weight: e.weight
}));
return data;
}
当我控制台记录它时,我可以清楚地看到它正在正确设置。但是,如果我尝试访问它或任何东西,它会一直抱怨它未定义。所以真正的主要问题是:定义从 API 端点接收的初始值的正确方法是什么。如果这只是一个专门针对一个实体的表单(比如一个练习),那么这会容易得多,因为它将是一个简单的 1:1 数据到表单中元素的映射
我正在尝试按如下方式定义我的表单:
const rootStore = useContext(RootStoreContext);
const {getExercises, exercises, exercisesForForm} = rootStore.workoutStore;
useEffect(() => {
if(match.params.workoutId) {
getExercises(match.params.workoutId);
}
}, [getExercises, match.params.workoutId])
<Formik key={uuid()} onSubmit={handleFormSubmit} initialValues={exercisesForForm} enableReinitialize={true}>
{({
handleSubmit,
handleChange,
values
}) => (
<Form onSubmit={handleSubmit}>
{exercises.map((exercise, index) =>
(
<Fragment key={exercise.id}>
<Header>{exercise.name}</Header>
<Form.Row>
<Form.Group as={Col}>
<Form.Label>Sets</Form.Label>
<Form.Control key={uuid()} type="number" name='sets' value={0} onChange={handleChange}/>
</Form.Group>
</Form.Row>
<Form.Row>
<Form.Group as={Col}>
<Form.Label>Reps</Form.Label>
<Form.Control key={uuid()} type="number" name='reps' onChange={handleChange}/>
</Form.Group>
</Form.Row>
<Form.Row>
<Form.Group as={Col}>
<Form.Label>Weight</Form.Label>
<Form.Control key={uuid()} type="number" name='weight' onChange={handleChange}/>
</Form.Group>
</Form.Row>
</Fragment>
)
)}
<Form.Row>
<Form.Group as={Col} controlId='04'>
<Button content="Submit" floated='right' type="submit"/>
</Form.Group>
</Form.Row>
</Form>
)}</Formik>
对此的后续问题是,如何正确定义表单的名称组件?在 MVC.NET 中(这是我最熟悉的网络方式)我会简单地定义一个数组并使用 @Html.TextBoxFor(x => x.Answers[i].Answer, new { type = "text" })
经过多次谷歌搜索、实验和重新阅读文档后,我终于弄明白了。我将代码更改为如下所示:
<Formik key={uuid()} onSubmit={handleFormSubmit} enableReinitialize={true} initialValues={exercisesForForm}
render={({values, handleChange, handleSubmit}) => (
<Form onSubmit={handleSubmit}>
{values.map((e, index) => (
<Fragment key={index}>
<Header>{e.name}</Header>
<Form.Row>
<Form.Group as={Col}>
<Form.Label>Sets</Form.Label>
<Form.Control key={`${index}_sets`} type='number' name={`[${index}].sets`} value={(e.sets)} onChange={handleChange} />
</Form.Group>
</Form.Row>
<Form.Row>
<Form.Group as={Col}>
<Form.Label>Reps</Form.Label>
<Form.Control key={`${index}_reps`} type='number' name={`[${index}].reps`} value={(e.reps)} onChange={handleChange} />
</Form.Group>
</Form.Row>
<Form.Row>
<Form.Group as={Col}>
<Form.Label>Weight</Form.Label>
<Form.Control key={`${index}_weight`} type='number' name={`[${index}].weight`} value={(e.weight)} onChange={handleChange} />
</Form.Group>
</Form.Row>
</Fragment>
)
)}
)}
<Form.Row>
<Form.Group as={Col} controlId='04'>
<Button content="Submit" floated='right' type="submit"/>
</Form.Group>
</Form.Row>
</Form>
)}
/>
有几点需要注意:我正在使用 values
属性 来访问初始值;我还使用索引来设置字段的名称。我认为是缺失的 link 将它们联系在一起。