【问题标题】:React Formik setFieldValue of other key value within same object反应同一对象内其他键值的Formik setFieldValue
【发布时间】:2021-08-13 14:36:49
【问题描述】:

我的目标是选择一个option select 值,一旦onChange 发生,它应该设置2 个Fields values 和setFieldValue,它们在同一个对象中具有键值对。

我的问题:为什么当我调用 setFieldValue('meta', value.meta) 时它没有返回键 meta 的值并且与 setFieldValue('description', value.description) 相同?

我不理解和做错了什么:value 的范围。如果id 的value 有一个对象子集,我可以使用.description 和.meta,但它在同一个对象内。我怎样才能正确访问它?

我使用过的示例:Formik Select with Other Option 和 Country and Regions

我的 json:

{
  "count": 2,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": "1",
      "created": "July 27, 2021, 10:21 PM",
      "modified": "August 12, 2021, 09:00 PM",
      "name": "Enter the Dragon",
      "description": "One of the greatest Kung Fu movies on my list.",
      "meta": {
        "director": "Robert Clouse",
        "studio": "Warner Bros",
      },
    },
    {
      "id": "2",
      "created": "July 27, 2021, 10:22 PM",
      "modified": "August 12, 2021, 09:01 PM",
      "name": "Iron Monkey",
      "description": "Another Kung Fu favorite.",
      "meta": {
        "director": "Yuen Wo Ping",
        "studio": "Warner Bros",
      },
    },
}

我的 useEffect 和 JSX:

const [movieList, setMovieList] = useState([]);

  useEffect(() => {
    const getMovieList = async () => {
      try {
        const { data } = await fetchContext.authAxios.get(`/movies/`);
        setMovieList(data.results);
        // console.log(data);
      } catch (err) {
        console.log(err);
      }
    };

    getMovieList();
  }, [fetchContext]);

  const initialValues = {
    collection_name: '',
    movies: [
      {
        name: '',
        order: '',
        label: '',
        meta: '',
        description: '',
      },
    ],
  };



<Formik initialValues={initialValues}>
          {({ isSubmitting, values, setFieldValue, handleChange }) => (
            <Form>
              <div className="row">
                <div className="col-md-6 col-xl-3">
                  <div className="form-group">
                    <label htmlFor="name">COLLECTION NAME</label>
                    <Field className="form-control" name="collection_name" type="text" />
                  </div>
                </div>
              </div>
              <div className="row">
                <div className="col-12">
                  <h3 className="pt-3">CREATE NEW COLLECTION</h3>
                </div>
              </div>
              <FieldArray name="movies">
                {({ insert, remove, push }) => (
                  <>
                    {values.movies.length > 0 &&
                      values.movies.map((index) => (
                        <div className="row" key={index}>
                          <div className="col-11">
                            <div className="row">
                              <div className="col">
                                <div className="form-group">
                                  <label
                                    htmlFor={`movies.${index}.name`}
                                  >
                                    NAME
                                  </label>
                                  <Field
                                    className="form-control"
                                    as="select"
                                    name={`movies.${index}.name`}
                                    onChange={(event) => {
                                      handleChange(event);
                                      const { value } = event.target;

                                      setFieldValue(`movies.${index}.meta`, value.meta);
                                      setFieldValue(`movies.${index}.description`, value.description);
                                    }}
                                  >
                                    <option defaultValue>...</option>
                                    {movieList &&
                                      movieList.map((i) => (
                                        <option key={i.id} value={i.id}>
                                          {i.name}
                                        </option>
                                      ))}
                                  </Field>
                                </div>
                              </div>
                              <div className="col">
                                <div className="form-group">
                                  <label
                                    htmlFor={`movies.${index}.order`}
                                  >
                                    ORDER
                                  </label>
                                  <Field
                                    className="form-control"
                                    name={`movies.${index}.order`}
                                    type="text"
                                  />
                                </div>
                              </div>
                              <div className="col">
                                <div className="form-group">
                                  <label
                                    htmlFor={`movies.${index}.label`}
                                  >
                                    LABEL
                                  </label>
                                  <Field
                                    className="form-control"
                                    name={`movies.${index}.label`}
                                    type="text"
                                  />
                                </div>
                              </div>
                            </div>
                            <div className="col">
                              <div className="form-group">
                                <label
                                  htmlFor={`movies.${index}.meta`}
                                >
                                  META DATA
                                </label>
                                <textarea
                                    value={values.meta}
                                    id="options"
                                    className="form-control"
                                    name={`movies.${index}.meta`}
                                    type="textarea"
                                    rows="4"
                                    onChange={handleChange}
                                />
                              </div>
                            </div>
                            <div className="col">
                              <div className="form-group">
                                <label
                                  htmlFor={`movies.${index}.description`}
                                >
                                  DESCRIPTION
                                </label>
                                <textarea
                                    value={values.description}
                                    id="options"
                                    className="form-control"
                                    name={`movies.${index}.description`}
                                    type="textarea"
                                    rows="4"
                                    onChange={handleChange}
                                />
                              </div>
                            </div>
                          </div>
                          <div className="col-1">
                            <button
                              type="button"
                              className="btn"
                              onClick={() => remove(index)}
                            >
                              Delete
                            </button>
                          </div>
                        </div>
                      ))}
                    <button
                      type="button"
                      className="btn"
                      onClick={() => push({ step: '', label: '' })}
                    >
                      Add Movie Fields
                    </button>
                  </>
                )}
              </FieldArray>
              <div className="my-3">
                <div className="border-bottom" />
              </div>
              <button
                className="btn primary_btn float-right mb-5"
                type="submit"
                disabled={isSubmitting}
              >
                SUBMIT
              </button>
            </Form>
          )}
        </Formik>

如果这已经回答了,请让我参考正确回答的问题。

【问题讨论】:

  • 问题不清楚。你能解释一下吗?你在哪里面临问题? .此外,如果可能的话,您可以创建一个代码沙箱来重现您的用例。
  • @Shyam 更新了问题,重点关注setFieldValue
  • 没有名为 meta 的字段值,因此 setFieldValue('meta', value.meta) 永远不会起作用 - 在您的初始值中 meta 是数组 movies 中的对象中的键
  • @StudioTime 在标签字段下方是包含meta 的元数据。请仔细阅读。

标签: reactjs json formik


【解决方案1】:

map 方法的第一个参数是数组中的项而不是索引。所以你需要把它改成

values.movies.map((movie, index) => (

您需要将 meta 和 description 传递给您的 setFieldValue,而不是传递

<Field
  className="form-control"
  as="select"
  name={`movies.${index}.name`}
  onChange={(event) => {
    handleChange(event);
    // find the selected movie from the movie list 
    const selectedMovie = movieList.find(movie => movie.id === event.target.value);

    setFieldValue(`movies.${index}.meta`, selectedMovie.meta);
    setFieldValue(`movies.${index}.description`, selectedMovie.description);
  }}
>
  <option defaultValue>...</option>
  {movieList &&
    movieList.map((i) => (
      <option key={i.id} value={i.id}>
        {i.name}
      </option>
    ))}
</Field>;

【讨论】:

  • 我添加了${index},但字段保持空白,没有呈现任何meta 或description。这是我有点困惑的地方。
  • 绝对是朝着正确方向迈出的一步!但是,我仍然返回“无法读取meta undefined 和description undefined 的属性”。
  • 当您在 select onChange 方法中使用控制台记录 selectedMovied 时会得到什么?
  • 不幸的是我收到了undefined
  • 控制台日志event.target.value 时得到的结果很奇怪?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-22
  • 1970-01-01
  • 2021-06-26
相关资源
最近更新 更多