iT邦幫忙

0

React 六角學院-學習筆記(Form 表單)

  • 分享至 

  • xImage
  •  

常見表單元素

label + input

function App() {
  const [inputState, setInputState] = useState([]);
  return (
    <>
      <label htmlFor="username">username {inputState}</label>
      <input
        type="text"
        id="username"
        value={inputState}
        onChange={(e) => {
          setInputState(e.target.value);
        }}
      />
    </>
  );
}

select && //multiSelect

function App() {
  const optionList = ["Taipei", "Taichung", "Kaohsiung"];
  const [selectState, setSelectState] = useState([]);
  return (
    <>
      {selectState}
      <select
        name=""
        id=""
        value={selectState}
        /*+ multiple={true} */
        onChange={(e) => {
          setSelectState(e.target.value);
           /*setSelectState(
            [...e.target.selectedOptions].map((option) => option.value)
          ); */
        }}
      >
        <option value="Choose the area" disabled>
          Choose the area
        </option>
        {optionList.map((location) => {
          return (
            <option value={location} key={location}>
              {location}
            </option>
          );
        })}
      </select>
    </>
  );
}

checkbox

function App() {
  const [check, setCheck] = useState(false);
  return (
    <>
      <label htmlFor="isCheck">確認狀態 {check.toString()}</label>
      <input
        type="checkbox"
        id="isCheck"
        onChange={(e) => {
          setCheck(e.target.checked);
        }}
        value={check}
      />
    </>
  );
}

checkList

function App() {
  const [checkList, setCheckList] = useState([]);
  const handleCheckList = (e) => {
    if (e.target.checked) {
      setCheckList([...checkList, e.target.value]);
    } else {
      setCheckList(checkList.filter((item) => item !== e.target.value));
    }
  };
  return (
    <>
      <label htmlFor="checkList1">item1</label>
      <input
        type="checkbox"
        id="checkList1"
        name="like"
        value="item1"
        onChange={handleCheckList}
      />
      <label htmlFor="checkList2">item2</label>
      <input
        type="checkbox"
        id="checkList2"
        name="like"
        value="item2"
        onChange={handleCheckList}
      />
      <label htmlFor="checkList3">item3</label>
      <input
        type="checkbox"
        id="checkList3"
        name="like"
        value="item3"
        onChange={handleCheckList}
      />
    </>
  );
}

Form && Submit

function App() {
  const [formData, setFormData] = useState({
    username: "test",
    password: "123321",
    isCheck: false,
  });
  const handleInputChange = (e) => {
    const value =
      e.target.type === "checkbox" ? e.target.checked : e.target.value;
    const name = e.target.name;
    setFormData({
      ...formData,
      [name]: value,
    });
  };
  const handleSubmit = (e) => {
    e.preventDefault();
    console.log(formData);
  };
  return (
    <>
      <form action="">
        <div className="mb-3">
          <label htmlFor="username" className="form-label">
            帳號
          </label>
          <input
            type="text"
            id="username"
            className="form-control"
            name="username"
            onChange={handleInputChange}
            value={formData.username}
          />
        </div>
        <div className="mb-3">
          <label htmlFor="password" className="form-label">
            密碼
          </label>
          <input
            type="text"
            id="password"
            className="form-control"
            name="password"
            onChange={handleInputChange}
            value={formData.password}
          />
        </div>
        <div className="mb-3">
          <label htmlFor="isCheck">確認狀態</label>
          <input
            type="checkbox"
            id="isCheck"
            className="isCheck"
            name="isCheck"
            onChange={handleInputChange}
            value={formData.isCheck}
          />
        </div>
        <button
          type="submit"
          className="btn btn-primary"
          onClick={handleSubmit}
        >
          送出
        </button>
      </form>
    </>
  );
}

onKeyDown鍵盤觸發搜尋

function App() {
  const [search, setSearch] = useState();
  const formHandleSubmit = (e) => {
    e.preventDefault();
    console.log("開始搜尋:", search);
  };
  const enterHandleSubmit = (e) => {
    if (e.key === "Enter") {
      console.log("開始搜尋:", search);
    }
  };
  return (
    <>
    {/* Way1 */}
      <form onSubmit={formHandleSubmit}>
        <div className="mb-3">
          <label htmlFor="search2" className="form-label">
            Search
          </label>
          <input
            type="text"
            name="search"
            id="search2"
            className="form-control"
          />
        </div>
      </form>
   {/* Way2 */}
      <label htmlFor="search1" className="form-label">
        Search
      </label>
      <input
        type="search"
        id="search1"
        className="form-control"
        name="search"
        value={search}
        onChange={(e) => {
          setSearch(e.target.value);
        }}
        onKeyDown={enterHandleSubmit}
      />
    </>
  );
}

React hook form (useForm)

建立環境
npm install react-hook-form

import { useForm } from "react-hook-form";
function App() {
  const { register, handleSubmit } = useForm();
  const onSubmit = (data) => {
    console.log(data);
  };
  return (
    <>
      <form action="" onSubmit={handleSubmit(onSubmit)}>
        <div>
          <label htmlFor="username" className="form-label"></label>
          <input
            type="text"
            name="username"
            id="username "
            defaultValue="Willy"
            {...register("username")} //'username'可在其他input換成email等其他data
            className="form-control"
          />
        </div>
        <button type="submit" className="btn btn-primary">
          註冊
        </button>
      </form>
    </>
  );
}

watch && useWatch

import { useForm } from "react-hook-form";

function App() {
  const { register, handleSubmit, watch, setValue, control } = useForm({
    defaultValues: {
      username: "Willy",
    },
  });
  const onSubmit = (data) => {
    console.log(data);
  };

  //watch
  // useEffect(() => {
  //   const subscription = watch((value, { name }) => {
  //     console.log(value, { name });
  //     if (name === "like") {
  //       setValue("username", "Will");
  //     }
  //   });
  //   console.log(subscription);
  //   return () => subscription.unsubscribe();
  // }, [watch]);

  //差異:useWatch 子層元件更新 不影響父層render
  const watchForm = useWatch({
    control,
  });
  useEffect(() => {
    console.log(watchForm);
  }, [watchForm]);

  return (
    <>
      <div>
        <form action="" onSubmit={handleSubmit(onSubmit)}>
          <div className="mb-3">
            <label htmlFor="username" className="form-label">
              Username
            </label>

            <input
              type="text"
              name="username"
              id="username"
              {...register("username")}
              className="form-control"
            />
          </div>
          <div className="mb-3">
            <label htmlFor="checkList1">item1</label>
            <input
              type="checkbox"
              name="like"
              id="checkList1"
              value="item1"
              {...register("like")}
            />
            <label htmlFor="checkList2">item2</label>
            <input
              type="checkbox"
              name="like"
              id="checkList2"
              value="item2"
              {...register("like")}
            />
            <label htmlFor="checkList3">item3</label>
            <input
              type="checkbox"
              name="like"
              id="checkList3"
              value="item3"
              {...register("like")}
            />
          </div>
          <button type="submit" className="btn btn-primary">
            Register
          </button>
        </form>
      </div>
    </>
  );
}

Form驗證 + 元件化

BS 驗證樣式
快速生成表單程式碼(官方)
form驗證方法
若未安裝bs 先在terminal 輸入
npm i bootstrap

 
import { useForm } from "react-hook-form";
import Checkbox from "./Checkbox";
import Input from "./Input";
function App() {
    const {
    register,
    formState: { errors },
    handleSubmit,
    getValues,
    control,
  } = useForm({});
  const onSubmit = (data) => console.log(data);

  console.log("errors:", errors);
  const checkbox = [
    { id: "checkList1", checkboxText: "item1" },
    { id: "checkList2", checkboxText: "item2" },
    {
      id: "checkList3",
      checkboxText: "item3",
      rules: {               //rules放第幾個都行(或是全放也可)
        required: {
          value: true,
          message: "至少勾選一項",
        },
      },
    },
    { id: "checkList4", checkboxText: "item4" },
    { id: "checkList5", checkboxText: "item5" },
  ];
  return (
    <>
      <div>
        <form action="" onSubmit={handleSubmit(onSubmit)}>
          <div className="mb-3">
            <Input
              register={register}
              errors={errors}
              id="username"
              labelText="Username"
              type="text"
              rules={{
                required: {
                  value: true,
                  message: "必填",
                },
              }}
            />
          </div>
          <div className="mb-3">
            <Input
              register={register}
              errors={errors}
              id="email"
              labelText="Email"
              type="email"
              rules={{
                required: {
                  value: true,
                  message: "必填",
                },
                pattern: {
                  value: /^\S+@\S+$/i,
                  message: "格式錯誤",
                },
              }}
            />
          </div>
          <div className="mb-3">
            <Input
              register={register}
              errors={errors}
              id="tel"
              labelText="Tel"
              type="tel"
              rules={{
                required: {
                  value: true,
                  message: "必填",
                },
                minLength: {
                  value: 8,
                  message: "至少8碼",
                },
                maxLength: {
                  value: 12,
                  message: "不超過12碼",
                },
              }}
            />
          </div>
          <div className="mb-3">
          {checkbox.map((checkbox, idx, arr) => (
            <Checkbox
              key={checkbox.id}
              register={register}
              errors={errors}
              type="checkbox"
              name="like"
              id={checkbox.id}
              checkboxText={checkbox.checkboxText}
              rules={checkbox.rules}
              checkboxLen={arr.length}
            />
          ))}
        </div>
          <button type="submit" className="btn btn-primary">
            Submit
          </button>
        </form>
      </div>
    </>
  );
}

export default App;

//Input.jsx

/* eslint-disable react/prop-types */
const Input = ({ register, errors, id, labelText, type, rules }) => {
  return (
    <div className="mb-3">
      <label htmlFor={id} className="form-label">
        {labelText}
      </label>
      <input
        type={type}
        name={id}
        id={id}
        {...register(id, rules)}
        className={`form-control ${errors[id] && "is-invalid"}`}
      />

      {errors[id] && (
        <div className="invalid-feedback">{errors?.[id]?.message}</div>
      )}
    </div>
  );
};

export default Input;

//Checkbox.jsx

/* eslint-disable react/prop-types */

const Checkbox = ({
  register,
  errors,
  type,
  name,
  id,
  rules,
  checkboxText,
  checkboxLen,
}) => {
  return (
    <div className="form-check">
      <input
        type={type}
        name={name}
        id={id}
        className={`form-check-input ${errors[name] && "is-invalid"}`}
        {...register(name, rules)}
        value={checkboxText}
      />
      <label htmlFor={id} className="form-check-label">
        {checkboxText}
      </label>
      {errors.like && id === `checkList${checkboxLen}` && (
        <div className="invalid-feedback">{errors?.like?.message}</div>
      )}
    </div>
  );
};

export default Checkbox;


加上axios 取得縣市地址


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言