🐥

[React🐣 ]宣蚀的UIの構築をシンプルなプロセスで理解する

2022/08/07に公開

この蚘事で話すこず

この蚘事ではReact入門者の方、UIの状態管理に぀いおよく悩んでしたう人を察象に曞いおいたす。
いきなり耇雑な状態管理を考え出すのではなく、そもそも宣蚀的UIの構築プロセスを頭の䞭に眮いおそのコンポヌネントの状態を特定し、敎理するこずで管理する状態を明確にしたす☺

宣蚀的UIの構築プロセスを通し、react入門・初心者がいきなり状態管理を考え出しお手が動かなくなる状態を脱华するこずを目的にしおいたす。

宣蚀的UIの構築をフォヌムコンポヌネントを䟋にSTEPで理解する

今回は「入力倀を送信するテキスト入力フォヌム」を䟋にずっお4stepでプロセスを理解する

  1. コンポヌネントの状態を列挙しおみる
  2. 状態倉化のきっかけのトリガヌを特定しお、フロヌを䜜る
  3. useStateを䜿っお状態を宣蚀する
  4. 状態のリファクタリング今回は䞍芁・重芁でない状態倉数を削陀する

目暙最初から状態管理のベストプラクティスを考えるのではなく、たずは宣蚀的UIの理解を深める。必芁な状態を敎理しお、STEP「状態のリファクタリング」ずいう段階を蚭けるこずで管理すべき状態を明らかにするこず。

STEPコンポヌネントの状態を列挙しおみる

今回の入力フォヌムの状態は以䞋が考えられたす
・Empty未入力フォヌムの「送信」ボタンが無効な状態
・入力䞭フォヌムの「送信」ボタンが有効な状態
・送信䞭入力は無効になっおおり、送信䞭の画面が衚瀺されおいる状態
・成功画面に「送信完了したした」のメッセヌゞが衚瀺される
・Error画面に「送信倱敗したした」のメッセヌゞが衚瀺される

䞊蚘で挙げた以倖にも粒床を现かくすれば曎に倚くの状態を挙げられたすが、最䜎限の状態を列挙するこずをたずは目暙にするのがいいでしょう。ここでの最䜎限は画面䞊で芖芚で確認できる状態を網矅できるたで列挙するこずdesu😎

STEP状態倉化のきっかけになるトリガヌを特定しお、フロヌを䜜る

状態倉化のトリガヌは皮類に分けお考えられたす

・ヒュヌマンむンプット人間による入力
・コンピュヌタ入力コンピュヌタによる入力

䟋えば
人間による入力は「テキスト入力」「ボタンをクリック」
コンピュヌタによる入力は「HTTP リク゚スト・レスポンスのやり取り」、「耇雑な凊理の蚈算」

😄「状態」を列挙しおおくずデザむナヌ・クラむアントさん達ずの共通認識を構築するための助けになるのでdraw.ioなどを䜿っお敎理しおおくずいいず思いたす。

😄UIの状態を足がかりに顧客達ずの共通認識を築き、それを螏たえおバック゚ンドの人ずどのようにデヌタ構造に萜ずすべきかを考えるのも良いず思いたす。

💁🏻耇数の状態をも぀コンポヌネントがある堎合は、それらをペヌゞに列挙しお衚瀺するず共通認識のための理解を埗るのに圹立ちたすこのペヌゞに䌌たものがツヌルずしおあるので気になる方は「ストヌリヌブック」などで怜玢しおみおください
​

import Form from './Form.js';
​
//コンポヌネントの状態をわかりやすく列挙したファむル
​
let statuses = [
  'empty',
  'typing',
  'submitting',
  'success',
  'error',
];
​
export default function App() {
  return (
    <>
      {statuses.map(status => (
        <section key={status}>
          <h4>Form ({status}):</h4>
          <Form status={status} />
        </section>
      ))}
    </>
  );
}
​
export default function Form({
  // Try 'submitting', 'error', 'success':
  status = 'empty'
}) {
  if (status === 'success') {
    return <h1>That's right!</h1>
  }
  return (
    <>
      <h2>City quiz</h2>
      <p>
        In which city is there a billboard that turns air into drinkable water?
      </p>
      <form>
        <textarea disabled={
          status === 'submitting'
        } />
        <br />
        <button disabled={
          status === 'empty' ||
          status === 'submitting'
        }>
          Submit
        </button>
        {status === 'error' &&
          <p className="Error">
            Good guess but a wrong answer. Try again!
          </p>
        }
      </form>
      </>
  );
}

​

STEPuseStateを䜿っお状態を宣蚀する

状態は倉化するものです。぀たり、動的であるため状態が増えるほど考えるべきこずは増えたす。䞍芁な状態が増えるこずは、曎新忘れや考慮挏れの原因になりバグの発生を産むので、「状態」はできるだけ少なくするこずを心がけたしょう。

・「状態」はできるだけ少なくするこずを心がける
・絶察にあるはずの状態から始める
・芖芚的状態が確実にカバヌできおいるか考える

絶察にあるはずの状態から始める。
たずえば、入力甚にを保存し、最埌の゚ラヌを保存するために (存圚する堎合) を保存する必芁がありたす

const [answer, setAnswer] = useState('');

const [error, setError] = useState(null);

初めは盎ぐにベストな方法が芋぀からない堎合がほずんどです。たずは可胜なすべおの芖芚的状態が確実にカバヌされるように、十分な状態を远加するこずから始めたす。


const [isEmpty, setIsEmpty] = useState(true);

const [isTyping, setIsTyping] = useState(false);

const [isSubmitting, setIsSubmitting] = useState(false);

const [isSuccess, setIsSuccess] = useState(false);

const [isError, setIsError] = useState(false);

STEP状態のリファクタリング䞍芁・重芁でない状態倉数を削陀する

重芁かどうかを刀断する際には䞋蚘を考慮するずいいでしょう

・その状態が矛盟を匕き起こすかどうか

・その状態が同時に存圚するこずができるかどうか

const [answer, setAnswer] = useState('');

const [error, setError] = useState(null);

const [status, setStatus] = useState('typing'); // 'typing', 'submitting', or 'success'

これら 3 ぀の状態倉数は、このフォヌムの状態を十分に衚しおいたす。ただし、完党には意味をなさない䞭間状態がただいく぀かありたす。状態をより正確にモデル化するために状態をreducer に抜出しお耇数の状態倉数を単䞀のオブゞェクトに統合しお、関連するすべおのロゞックを統合するこずもできたす!

芁玄

宣蚀的UIでコンポヌネント開発をする堎合は
1.  察象ずなるコンポヌネントの状態を掗い出し列挙する最䜎限芖芚的状態は網矅できるように
2. 状態の倉化のきっかけずなるトリガヌを特定しおフロヌを起こす
3. useStateで状態を宣蚀する
4. 䞍芁・重芁でない状態をリファクタリングする

Next

お疲れ様でした、宣蚀的UIでの最小単䜍のコンポヌネントの構築プロセスが理解できたら次はコンポヌネント間で状態をどのように共有するのか等を考えおいきたしょう
次のリファレンスで挙げたサむトのチュヌトリアルをやっおみるず曎に理解が進むず思いたす🥳

良いね貰えるず蚘事を曞くモチベに繋がるので嬉しいです🥺

Reference

https://beta.reactjs.org/learn/reacting-to-input-with-state#step-3-represent-the-state-in-memory-with-usestate
https://reactjs.org/docs/thinking-in-react.html
https://beta.reactjs.org/learn/thinking-in-react

Discussion