如何使用React Hook Forms Field Array从服务器设置动态数组的复选框值

问题描述 投票:0回答:1

我的服务器返回一个如下所示的对象:

{
  "success": true,
  "user_groups": {
    "user_id": 6,
    "username": "sbosell",
    "first_name": "Steve",
    "last_name": "Bosell",
    "email": "[email protected]",
    "is_staff": false,
    "is_active": true,
    "is_superuser": false,
    "groups": [
      { "id": 1, "name": "Admin", "value": false },
      { "id": 3, "name": "Managers", "value": false },
      { "id": 4, "name": "Users", "value": true },
      { "id": 5, "name": "Stakeholders", "value": false }
    ]
  }
}

我的需求是:

  1. 在表单中将所有字段显示为可编辑(当前显示除组之外的所有字段)
  2. 为每个组显示一行,并带有指示当前值的复选框
  3. 它必须动态工作,因为可能会创建新组或销毁现有组。

这是我到目前为止的代码(不完整,但我现在专注于显示部分)..请注意我过去尝试过但没有工作的注释行。

我当前的目标是让复选框显示正确的状态(在这个特定的用例中,前两个和最后一个框不应被选中,但用户组的一个应该被选中。然而,实际发生的情况是所有复选框都被选中无论我尝试什么,总是检查。

注意:我没有使用任何 UI 工具包,只是简单的旧 HTML。

建议?

import React, { useState, useEffect } from "react";
import { useForm, useFieldArray } from "react-hook-form";
import { ErrorMessage } from "@hookform/error-message";
import { RootStateOrAny, useSelector, useDispatch } from "react-redux";
import { Link, Outlet, useParams, useNavigate } from "react-router-dom";
import {
  userGetGroupsAction,
  userUpdateRequestAction,
} from "../../actions/adminActions";

interface FormInputs {
  email: string;
  firstName: string;
  lastName: string;
  username: string;
  isActive: boolean;
  isStaff: boolean;
  isSuperuser: boolean;
  group: {
    groupId: any;
    name: any;
    value: boolean;
  }[];
}

export default function User() {
  const {
    register,
    control,
    formState: { errors },
    handleSubmit,
    setValue,
  } = useForm<FormInputs>();
  const users = useSelector((state: RootStateOrAny) => state.admin.users);
  const subject = useSelector(
    (state: RootStateOrAny) => state.admin.user_groups,
  );

  const { mode, user_id } = useParams();

  const navigate = useNavigate();
  const dispatch = useDispatch();

  const exitModal = () => {
    navigate("/admin/user");
  };

  const { fields, append, remove } = useFieldArray({
    name: "group",
    control,
  });

  useEffect(() => {
    if (user_id) {
      dispatch(userGetGroupsAction(user_id));
    }
  }, [user_id]);

  useEffect(() => {
    if (subject) {
      setValue("username", subject.username);
      setValue("firstName", subject.first_name);
      setValue("lastName", subject.last_name);
      setValue("email", subject.email);
      setValue("isActive", subject.is_active);
      setValue("isStaff", subject.is_staff);
      setValue("isSuperuser", subject.is_superuser);

      remove();

      subject.groups.map((group: any, index: number) => {
        append({
          groupId: group.id,
          name: group.name,
          value: group.value,
        });
        //console.log('derp' + group.value);
        //setValue(`group.${index}.value`, group.value);

        /*
            setValue("group", [{
              groupId: group.id,
              name: group.name,
              value: group.value
            }]);
            */

        //setValue("group", [index][group.value]);
      });
    }
  }, [subject]);

  const onSubmit = handleSubmit(async (data: FormInputs) => {
    dispatch(userUpdateRequestAction(data));
  });
  const [updateCount, forceUpdate] = useState(0);
  const clearError = (field: string) => {
    subject.response[field] = false;
    forceUpdate(updateCount + 1);
  };

  const userList = users.map((user: any) => (
    <tr key={user.id}>
      <td>{user.username}</td>
      <td>{user.first_name}</td>
      <td>{user.last_name}</td>
      <td>{user.email}</td>
      <td>
        <Link to={"/admin/user/edit/" + user.id}>Edit</Link>
      </td>
    </tr>
  ));

  return (
    <div>
      <h4 className="pageTitle">User Maintenance</h4>
      <table>
        <thead>
          <tr>
            <th>Username</th>
            <th>First Name</th>
            <th>Last Name</th>
            <th>Email</th>
            <th></th>
          </tr>
        </thead>
        <tbody>
          {users && userList}
          {users.length === 0 && (
            <tr>
              <td colSpan={5}>There are no Users set up yet</td>
            </tr>
          )}
        </tbody>
      </table>
      {mode === "edit" && subject && (
        <>
          <div className="screenBlocker" onClick={exitModal}></div>
          <div className="modalLarge">
            <div className="modalHeader">
              Edit User: {subject.first_name} {subject.last_name}
              <span onClick={exitModal}>x</span>
            </div>
            <div className="modalContent">
              <form onSubmit={onSubmit}>
                <div className="halfLeft">
                  <div>
                    <label>Username</label>
                    <input
                      {...register("username", {
                        required: "Username is required",
                      })}
                      onClick={() => clearError("username")}
                    />
                    <ErrorMessage errors={errors} name="username" />
                    {subject.response && subject.response.username && (
                      <span>{subject.response.username[0]}</span>
                    )}
                  </div>
                  <div>
                    <label>First Name</label>
                    <input {...register("firstName")} />
                  </div>
                  <div>
                    <label>Last Name</label>
                    <input {...register("lastName")} />
                  </div>
                  <div>
                    <label>Email</label>
                    <input
                      className="wideInput1"
                      {...register("email", { required: "Email is required" })}
                    />
                    <ErrorMessage errors={errors} name="email" />
                    {subject.response && subject.response.email && (
                      <span>{subject.response.email[0]}</span>
                    )}
                  </div>
                </div>
                <div className="halfRight">
                  <label>Global Settings</label>
                  <div>
                    <input
                      className="checkbox"
                      type="checkbox"
                      {...register("isActive")}
                    />
                    <label className="checkboxLabel" htmlFor="isActive">
                      Active
                    </label>
                  </div>
                  <div>
                    <input
                      className="checkbox"
                      type="checkbox"
                      {...register("isStaff")}
                    />
                    <label className="checkboxLabel" htmlFor="isStaff">
                      Staff
                    </label>
                  </div>
                  <div>
                    <input
                      className="checkbox"
                      type="checkbox"
                      {...register("isSuperuser")}
                    />
                    <label className="checkboxLabel" htmlFor="isSuperuser">
                      Superuser
                    </label>
                  </div>
                </div>
                <div className="bottomHalf">
                  <label>User's Groups</label>
                  {fields.map((item, index) => (
                    <div key={item.id}>
                      <input
                        className="checkbox"
                        type="checkbox"
                        {...register(`group.${index}.name`)}
                      />
                      <label
                        className="checkboxLabel"
                        htmlFor={`group.${index}.name`}
                      >
                        {item.name}
                      </label>
                    </div>
                  ))}
                </div>
                <input type="submit" />
              </form>
            </div>
          </div>
        </>
      )}
    </div>
  );
}
checkbox react-hook-form
1个回答
4
投票

{fields.map((item, index) => (
                  <div key={item.id}>
                    <input className="checkbox" type="checkbox" {...register(`group.${index}.value`)} />
                    <label className="checkboxLabel" htmlFor={`group.${index}.value`}>{item.name}</label>
                  </div>
                ))}

这是您的群组数据:

"groups": [
       {"id": 1, "name": "Admin", "value": false}, 
       {"id": 3, "name": "Managers", "value": false}, 
       {"id": 4, "name": "Users", "value": true}, 
       {"id": 5, "name": "Stakeholders", "value": false}
     ]

这是代表该数据的表格:

"groups": [
       {"id": 1, "name": "Admin", "value": false}, 
       {"id": 3, "name": "Managers", "value": false}, 
       {"id": 4, "name": "Users", "value": true}, 
       {"id": 5, "name": "Stakeholders", "value": false}
     ]
     
     
     field.map((item, index) => {
        return <div>
           <input type='text' name={`group.${index}.name`}/>
           <input type='check' name={`group.${index}.value`}/>
        <div/>
     })

因此,输入将始终被表示并与其值相关联,不要混合它们。

© www.soinside.com 2019 - 2024. All rights reserved.