[Redux]Reduxミッドレンジ-文字列の入力/削除と画面での実装


1.Reduxを使用して文字列を入力/削除し、画面を実装


文字列を受信して画面に表示する論理を実現します.

2.基本構造の構成


基本的なstore、reduceなどのredox構造とHTMLを構築します.

2-1. HTMLテンプレートの設定


まず画面を構成し、各tagプロパティを定義します.
<body>
    <h1>To Do LIST</h1>
    <form>
      <input type="text" placeholder="Write to do" />
      <button>Add</button>
    </form>
    <ul></ul>
  </body>
  • フォームtagにinput/buttonを入れます.
  • inputtagで文字列を受信しbuttonでイベントをトリガーします.
    ※formtagはすべてaddEventListener(submit)を生成するように構成され、文字列入力とボタンクリックはイベントを生成して相互に接続するように構成されています.

  • 2-2. Redux環境設定

    import {createStore} from 'redux'
    
    const form = document.querySelector("form")
    const input = document.querySelector("input")
    const ul = document.querySelector("ul")
    
    const ADD_TODO = "ADD_TODO"
    const DELETE_TODO = "DELETE_TODO"
    
    const reducer = (state = [], action) => {
      switch(action.type){
        case ADD_TODO : return []
        case DELETE_TODO : return []
        default : return state
      }
    }
    
    const store = createStore(reducer)
    上記のコードに示すようにform,input,ul tagをdocumentとする.querySelectorで接続します.
    その後storeを作成し、基本的なreduce構造を作成します.
    actionの分岐点に理由switchで構成されています.

    2-3. addEventListener(イベント設定と論理接続)


    イベントを接続し、アクションと入力された文字列(テキスト)をdispatchで送信します.
    const onSubmit = e => {
      e.preventDefault()
    
      const toDO = input.value
      input.value = ""
    
      store.dispatch({type : "ADD_ToDo", text : toDO})
    }
    
    form.addEventListener("submit", onSubmit)
    form内部で発生するすべてのイベント(ここではADDボタンをクリックしたときのsubmitイベント)に対してイベント設定を行い、onSubmit関数を呼び出して論理を起動します.
    onSubmitで動作をキャンセルします.
  • ADD TODOタイプは、ADD TODOブランチ処理(入力を追加した文字列)に用いられる.
  • このとき入力された文字列はdispatchとともに伝達され、input.最終的に転送変数とtoDO変数にvalueで格納されます.
  • onSubmitは、サブタグのイベント(特にonClick)を実質的に検出し、サブタグの値を確保するフックです.
  • ※prventDefault(prventDefault)は、ブラウザでアクティビティの実行時に自分で操作するアクティビティを強制的にブロックする機能です.
    ※dispatchではactionだけでなく、他にも様々なオブジェクトや変数を渡すことができます.

    2-4. ログ出力action出力を表示

    console.log(action)
    受け取ったactionをlogに出力して、出力のパラメータが何なのか見てみましょう.

    dispatchで受け取ったactionパラメータtypeとtextはすべて受け取った.
    特にtextはinputvalue、すなわち、入力された文字列は依然として伝達される.
    この機能により、画面に文字列を表示または削除する機能をさらに実現できます.

    3.ステータスの変化を反映し、購読して表示する


    subscribeにより変化した状態(ログ出力)を実現する.

    3-1. subscribe


    テキストオブジェクト(変化状態)をdispatchで渡し、subscribeで接続します.
    const reducer = (state = [], action) => {
      console.log(action)
      switch(action.type){
        case ADD_TODO : return [...state, { text : action.text } ]
        case DELETE_TODO : return []
        default : return state
      }
    }
    新しいオブジェクトを返すと、既存のステータス(..state)と新しいステータスオブジェクト(text:action.text)が反映されます.

    3-2. ログチェック

    store.subscribe(() => console.log(store.getState()))
    上記のreduce logicで変化するstateを受信すると、それを購読してlogicを出力します.

    既存の状態の「共配列」状態では、変化したオブジェクトが「配列」(state)に蓄積されることがわかります.
  • ステータス配列に追加されたオブジェクトが蓄積されます.
  • によって蓄積されたオブジェクトは、配列のインデックス空間(=インデックス)に格納される.
  • 状態のgetState、すなわち現在の状態は、累積オブジェクトが格納された配列状態である.
  • 3-3. ステータス反映で画面に表示


    内部テキストに新しいタグを作成し、入力したテキストを作成します.
    新しいタグに割り当てるid(唯一のパラメータ)のid値を、割り当て項目に追加します.
    const reducer = (state = [], action) => {
      console.log(action)
      switch(action.type){
        case ADD_TODO : return [...state, { text : action.text, id : action.id } ]
        case DELETE_TODO : return []
        default : return state
      }
    }
    
    const onSubmit = e => {
      e.preventDefault()
    
      const toDO = input.value
      input.value = ""
    
      store.dispatch({type : "ADD_TODO", text : toDO, id: Date.now()})
    }
    actionパラメータを渡す場合、dispatchでtextとid値を渡します.
    ※この場合id値はDateとなります.nowで生成します.
    const paintTextToView = () => {
      const lists = store.getState()
      ul.innerHTML = ""
    
      lists.forEach(listItem => {
        const li = document.createElement("li")
        li.id = listItem.id
        li.innerText = listItem.text
        ul.appendChild(li)
      })
    }
    
    store.subscribe(paintTextToView)
    渡されたオブジェクト(text,id値)を使用して、liタグを作成するときに(document.createElement(「li」)画面に入力したテキストが表示されます.
    上の論理の流れを以下に示す.
  • addボタンを押すとsubmitイベントが起動し、subscribeでpaintTexttoView関数が実行されます.
  • getStateで変化する状態値(action.text積算の状態配列)を取得します.
  • この状態値の要素をループし、liタグを生成し、画面上で実装する(innerText).
  • によって生成されたli属性は、ultagサブアイテム(appendChild)に属する.
  • ※受信したオブジェクトはそのままloop(forEach)で累積した配列状態をコピーし、既存のInnerHTML属性をそのまま配列し、最近反映した要素値のみを生成します.

    3-4. 実装された画面の表示



    論理が正常に動作しているかどうかを確認します.

    3-5. (関連項目)reduce return順の実装画面


    オブジェクトを返す順序を変更すると、画面上の表示方法を変更することもできます.
    case ADD_TODO : return [{ text : action.text, id : action.id }, ...state,  ]
    上記のコードで返される配列の様子を新しく生成されたオブジェクト-既存のstate配列の順に並べた場合、最終的にgetStateで渡される構造も、新しいオブジェクト-既存のstate({.state})の順に画面に表示されます.
    returnではすべての配列要素が渡されるので、順序とともにul.画面上で変更要素を実装できるのはinnerHTML=""の前だけであることを覚えておいてください.

    4.画面に表示されている文字列を削除


    画面に文字列を作成するたびに、DELETEボタンが作成されます.
    該当するボタンを押して削除ロジックを構成します.

    4-1. 文字列の作成時にbuttonを作成する


    createElementボタンを作成することもできます.
    lists.forEach(listItem => {
        const li = document.createElement("li")
        const btn = document.createElement("button")
    
        li.id = listItem.id
        li.innerText = listItem.text
        ul.appendChild(li)
        
        btn.innerText = "DELETE the list"
        li.appendChild(btn)
      })
    subscribeは文字列を同時に生成し,button tagも共に生成する.
    このボタンtagは文字列と同様に、親tagをliに構成します.

    4-2. Deleteボタンと削除項目のid関連付け


    DeleteボタンをDeleteボタンを生成する親ラベルliのid値に関連付けます.
    btn.innerText = "DELETE the list"
        btn.addEventListener("click", (e) => {console.log(e.target.parentNode.id)})
        li.appendChild(btn)
    clickイベントの実行時
    実行イベントのtag属性は
  • e.targetで取得できます.
  • e.target.parentNode.idによって、タグが属する親タグli tag id値が確保されます.
  • その後、
  • で取得したid値を削除する論理を構成するように設定される.

  • 4-3. 削除操作のスケジュールと減速機内部ロジックの構成


    イベントが発生するとactionが割り当てられ、actionを介してid値が渡されます.
    実際には、id値を削除するロジックはreduce内部で組織されています.
    btn.innerText = "DELETE the list"
        btn.addEventListener("click", (e) => {
          const id = e.target.parentNode.id
          store.dispatch({ type : "DELETE_TODO", id })
        })
        li.appendChild(btn)
    DELETEボタンをクリックするとclickイベントがトリガーされ、削除する要素のid値をaction dispatchで渡す構造が構成されます.
    また、DELETERボタンを押すと、減速機定義の削除タイプがオブジェクト化され({type:"DELETE TODO"})、減速機内部で対応する論理操作が実行されます.
    const reducer = (state = [], action) => {
      console.log(action)
      switch(action.type){
        case ADD_TODO : return [{ text : action.text, id : action.id }, ...state,  ]
        case DELETE_TODO : return state.filter
        default : return state
      }
    }
    reduce内部では、対応するアクションが受信され、受信されたタイプとidによってどの削除ロジックを実現すべきかが考慮されます.

    4-4. array.フィルタによる新しいオブジェクト戻り構造の構成(論理の削除)


    削除ロジックを構成するコア要素には以下の2つの要素がある.
  • dispatch送信動作タイプ
  • dispatchで送信動作のid
  • この要素を使用せずにstate(push、accountなど)を直接変更します.
    filter関数を使用して、新しいオブジェクト値(配列)を返します.
    const reducer = (state = [], action) => {
      console.log(action)
      switch(action.type){
        case ADD_TODO : return [{ text : action.text, id : action.id }, ...state]
        case DELETE_TODO : return state.filter(deletedList => deletedList.id !== Number(action.id))
        default : return state
      }
    }
    削除タイプは、上記のコードに示すように、削除ロジックを実現します.
  • state.フィルタにより、現在表示されている配列状態では、条件を満たす配列のみが返され、画面に表示されます.
  • forEachループ配列のすべての要素は、id値を使用するため、条件を処理する際に考慮されます.
  • の条件を満たす要素を返して画面上で実装すればよく、id値が他の要素のみをstateに反映する場合、id値以外の要素がstateに表示されます.
  • この状態にid値は含まれていないため、削除の効果があります.
  • 4-5. 削除ロジックの確認



    論理が正常に動作しているかどうかを確認します.
    (※画面で2番目を削除している様子)

    5.参照リンク


    arrayに関するJavaScriptメソッドの公式ドキュメント(filterを参照)
    https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/splice
    event.preventDefault
    https://pa-pico.tistory.com/20