🐙
子コンポーネントから親コンポーネントにstate経由で値を渡す
家計簿アプリを作っていて、全体の金額を表示している画面で、明細行を削除する場合、明細削除時に全体の金額からも数字を引く必要があります。
子コンポーネントの明細行の削除ボタン起因で、親コンポーネントの金額を更新します。制御はこちらの記事を参考にさせていただきました。
現状とやりたいこと
- 親で金額を表示している。
- 金額は親で定義したinterfaceと変数で管理する。
- 親から子にsetStateを渡す。
- 子のボタン押下を起点に親の表示を更新する。
子コンポーネント
親からWalletという定義とsetStateを受け取る。行を削除したらsetStateを呼んで親の金額を更新する。(行の表示ロジックは省略)
child.tsx
interface Wallet {
id: string
name: string
balance: number
}
export default function Journal(props: { wallet: Wallet; setWallet: any }) {
interface Come {
id: string
amount: number
createdAt: string
}
const deleteRow = (id: string, amount: number) => {
props.setWallet(amount);
setComeData(() => {
return comeData.filter((Come) => {
return Come.id !== id;
})
})
}
return (
<div>
<table className="border-separate border-spacing-2">
<thead>
<tr>
<th>金額</th>
<th>登録時間</th>
<th>削除</th>
</tr>
</thead>
<tbody>
{comeData.map((item: Come, index) => (
<tr key={index}>
<td className="text-right">{item.amount}</td>
<td>{item.createdAt}</td>
<td>
<button
type="button"
className="rounded bg-gray-200 p-2 transition-colors hover:bg-gray-300"
onClick={() => deleteRow(item.id, item.amount)}
>
削除
</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
親コンポーネント
子の削除ボタンが押下されたら balanceUpdate をcallして 金額:{walletData.balance} を更新する。
parent.tsx
export default function Page() {
interface Wallet {
id: string
name: string
balance: number
}
const [walletData, setWalletData] = useState<Wallet | null>(null)
const balanceUpdate = (amount: number) => {
setWalletData((prev) => {
if (prev) {
return { ...prev, balance: prev.balance - amount }
}
return prev
})
}
return (
<div>
<h1>{walletData.name || "No Title Available"}に参加しているユーザー</h1>
<h1>金額:{walletData.balance}</h1>
<OutcomeForm wallet={{ id: walletData.id }} />
<Journal wallet={walletData} setWallet={balanceUpdate} />
</div>
)
}
現代において画面全体をリロードすると時間がかかり、ユーザーがストレスを感じるので、変更箇所だけ更新する必要があります。コンポーネント間の値や関数の渡し方が実践できました。親と子どちらにも関数を書く事ができるので、明確に制限するなどして、一貫性のある仕組みを検討したい。
Discussion