React hooks에서 여러 checkbox를 구현해보십시오.

useState와 useEffect를 사용하여 여러 checkbox를 구현해보십시오.



여러가지 탐구로 써 보았으므로 메모에 남겨 둔다.

사양에 대해


  • 체크 박스가 1 개 이상 checked 되었을 경우만 송신 버튼을 표시시키고 싶다.
  • checked 아이템의 id를, 송신 버튼이 눌린 타이밍으로 배열로 송신하고 싶다.

  • checkBox.jsx
    import React, { useState, useEffect } from "react"
    
    //checkboxのvalueリスト
    const checkLists = [
      "パン",
      "おにぎり",
      "焼き肉",
      "ラーメン",
      "たこ焼き",
      "アイスクリーム",
    ]
    
    //checkboxコンポーネント
    const CheckBox = ({id, value, checked, onChange}) => {
      return (
        <input
          id={id}
          type="checkbox"
          name="inputNames"
          checked={checked}
          onChange={onChange}
          value={value}
        />
      )
    }
    
    const CheckBoxList = () => {
    
    //checkedItemsは初期値を空のオブジェクトにする
      const [checkedItems, setCheckedItems] = useState({})
    //ひとつでもcheckedになっている場合にのみ送信ボタンを表示させたいので、全体のStateを監視する
      const [isBtnHide, setIsBtnHide] = useState(true)
    
      useEffect(() => {
    //checkedItemsが空では無い場合、送信ボタンを表示させる
        Object.keys(checkedItems).length && setIsBtnHide(false)
    //すべてのcheckedItemの値がfalseの場合に送信ボタンを表示させる
        setTimeout(() => {
          if (
            Object.values(checkedItems).every(checkedItem => {
              return checkedItem === false
            })
          ) {
            setIsBtnHide(true)
          }
        },100);
      }, [checkedItems])
    
      const handleChange = e => {
    //checkedItemsのstateをセット
        setCheckedItems({
          ...checkedItems,
          [e.target.id]: e.target.checked
        })
        console.log('checkedItems:', checkedItems)
      }
    
      const dataSendBtn = e => {
    //既定のイベントをキャンセルさせる
        e.preventDefault()
    //送信ボタンを押したタイミングで、checkedItemsオブジェクトのvalueがtrueのkeyのみを配列にしてconsoleに表示させる
        const dataPushArray = Object.entries(checkedItems).reduce((pre,[key, value])=>{
          value && pre.push(key)
          return pre
        },[])
        console.log("dataPushArray:", dataPushArray)
      }
    
      return (
        <>
          <h2>好きな食べ物</h2>
          <form>
            {checkLists.map((item, index) => {
              index = index + 1
              return (
                <label htmlFor={`id_${index}`} key={`key_${index}`}>
                  <CheckBox
                    id={`id_${index}`}
                    value={item}
                    onChange={handleChange}
                    checked={checkedItems[item.id]}
                  />
                  {item}
                </label>
              )
            })}
    {/* checkedがない場合には送信ボタンを表示させない */}
            {!isBtnHide && <button onClick={dataSendBtn}>アンケート送信ボタン</button>}
          </form>
        </>
      )
    }
    
    export default CheckBoxList
    
    
    



    우선 의도한 대로의 움직임이 되었다.
    하지만 어쩐지 돌아다니고 있는 것 같다. . . .

    new Map()에서의 구현


     const [ischecked, toggleChecked] = useState(new Map())
    

    Map은 state를 업데이트하기 때문에 (재 렌더를 트리거하기 위해) Map을 new Map으로 바꿔야합니다.
    const handleChange = e => {
      checkedItems.set(e.target.id, e.target.checked)
      setCheckedItems(new Map(checkedItems) );
      console.log("checkedItems: ", checkedItems);
    }
    

    20200712 추가


    for를 사용하는 것은 좋지 않습니다. . . 지적되었으므로 다시 작성했습니다.

    before
    const dataPushArray = []
    for (let [key, value] of Object.entries(checkedItems)) {
      if (value) {
        dataPushArray.push(key)
      }
    }
    console.log("dataPushArray:", dataPushArray)
    

    after
    const dataPushArray = Object.entries(checkedItems).reduce((pre,[key, value])=>{
      value && pre.push(key)
      return pre
    },[])
    console.log("dataPushArray:", dataPushArray)
    

    더 좋은 방법은 없거나, 여러가지 생각해 본다, 추기해 간다

    좋은 웹페이지 즐겨찾기