Reactにおける状態のリフトアップ

複数のコンポーネントが同じ変化するデータを反映する必要があることがよくあります。Reactでは、 共通の状態を最も近い共通の祖先コンポーネントに「リフトアップ」することが推奨されています。 例を見てみましょう。

水温計算機を作りたいとします。 これは、ユーザーが温度を入力する入力フィールドと、 判定(水は液体、固体、気体)を表示する段落で構成されます。

この計算機が Calculator というコンテナコンポーネントであるとします:

jsxfunction Calculator() {
  return <div>
    
  </div>;
}

温度を入力するフィールドを TempInp コンポーネントに、 判定を表示する段落を Verdict コンポーネントに分離しましょう:

jsxfunction Calculator() {
  return <div>
    <Verdict />
    <TempInp />
  </div>;
}

TempInp と Verdict の両方が温度の状態を持つ必要があることは簡単に理解できます。 そして、論理的にはこれは同じ温度であるべきです: 入力フィールドにデータが入力されると、判定が表示されなければなりません。

このような場合、状態のリフトアップと呼ばれる手法を使うことが推奨されます: 2つ(またはそれ以上)のコンポーネントで共通する状態は、 それらの共通の親コンポーネントまで「持ち上げ」られます。

今回のケースでは、温度の状態は Calculator コンポーネントに属することになり、 TempInp と Verdict に props として渡されます:

jsxfunction Calculator() {
  const [temp, setTemp] = useState(0);
  
  return <div>
    <Verdict temp={temp} />
    <TempInp temp={temp} />
  </div>;
}

TempInp コンポーネントには温度を変更する入力フィールドが必要です。 しかし、この温度はこのコンポーネントの props であるため、 TempInp 内で直接変更することはできません。 正しくは、Calculator コンポーネントから温度を変更するための特別な関数を渡すことです:

jsxfunction Calculator() {
  const [temp, setTemp] = useState(0);
  
  function changeTemp(event) {
    setTemp(event.target.value);
  }
  
  return <div>
    <Verdict temp={temp} />
    <TempInp temp={temp} changeTemp={changeTemp} />
  </div>;
}

ちなみに、新しい関数を導入する代わりに、 子コンポーネントに setTemp 関数をそのまま渡すこともできます:

jsxfunction Calculator() {
  const [temp, setTemp] = useState(0);
  
  return <div>
    <Verdict temp={temp} />
    <TempInp temp={temp} setTemp={setTemp} />
  </div>;
}
Задание 1

TempInp と Verdict コンポーネントの実装を書いてください。

Задание 2

状態のリフトアップを使用する必要がある3つのタスクを考えてください。 これらのタスクの解決策を書いてください。