📝

【React】子コンポーネントで値を操作し、親コンポーネントで条件付きレンダー

2022/04/11に公開4

全体のコード

pages/childToParent/index.tsx
import Parent from '../../components/childToParent/Parent'

export const App = () => {
  return (
    <>
      <Parent />
    </>
  )
}

export default App
components/childToParent/Parent.tsx
import { useState } from 'react'
import Child from './Child'

export const Parent = () => {
  const [animalName, setAnimalName] = useState('dog')

  return (
    <>
      <div>animalName:{animalName}</div>
      {animalName === `pig` && <div>子コンポーネントで`pig`を設定しました</div>}
      <Child setAnimalName={setAnimalName} />
    </>
  )
}

export default Parent
components/childToParent/Child.tsx
import { useEffect } from 'react'

type Props = {
  setAnimalName: React.Dispatch<React.SetStateAction<string>>
}

export const Child = ({ setAnimalName }: Props) => {
  useEffect(() => {
    const newAnimalName = `pig`
    setAnimalName(newAnimalName)
  }, [])

  return <div>子コンポーネント</div>
}

export default Child

説明

Next.js + TypeScriptの環境で書いています。

ここで子コンポーネント Child を呼び出すか否かで処理が変わります。
かなり簡略化したコードですが、
子要素の数に応じて親?のタイトルを変えるとか、
だいたい似たような処理でできます。

子コンポーネント Child を呼び出さない場合

components/childToParent/Parent.tsx
{/* <Child setAnimalName={setAnimalName} />


useState初期値のままの値が入っている。

子コンポーネント Child を呼び出す場合

components/childToParent/Parent.tsx
<Child setAnimalName={setAnimalName} />


子コンポーネントでstateの中身をいじったデータが入っている。
中身がpigだった場合の条件付きレンダーも機能している。

Discussion

🐏🐏
setAnimalName: React.Dispatch<React.SetStateAction<string>>

都度こう書くのは大変なのでpropsで利用する分には下記の方法でも型的には問題ないと思います!

setAnimalName: (string)=>void
dev63dev63

おお!教えて頂きありがとうございます!
試してみます。

🐏🐏

正しくはこうでした🙏
setAnimalName: (name: string)=>void
更新前の値を利用する場合はSetStateActionを使用することで下記の様な記法が使えますが、input tagの入力によって更新するケースは基本上記の記法で足りると思います!
setAnimalName((prev)=>prev + newValue)

dev63dev63

今日時間があったので、実際に試してみました!
下記の 型の変更 の記述で元のコードと同じ動作になること、
SetStateActionで更新前の 'dog'に更新後は 'pig' を付け足せることを確認できました!
教えて頂きありがとうございます!

型の変更

import { useEffect } from 'react'

type Props = {
  setAnimalName: (name: string)=>void
}

export const Child = ({ setAnimalName }: Props) => {
  useEffect(() => {
    const newAnimalName = `pig`
    setAnimalName(newAnimalName)
  }, [])

  return <div>子コンポーネント</div>
}

export default Child

SetStateActionの利用

import { Dispatch, SetStateAction, useEffect } from 'react'

type Props = {
  setAnimalName: Dispatch<SetStateAction<string>>
}

export const Child = ({ setAnimalName }: Props) => {
  useEffect(() => {
    const newAnimalName = `pig`
    setAnimalName((name: string) => name + newAnimalName) 
  }, [])

  return <div>子コンポーネント</div>
}

export default Child