親から渡ってきた children に props を追加したかったので、その個人的な備忘録です。
やりたいこと
- 親Componentから 共通Component を children として 子Componentへ渡す
- 子Component側で持つべきメソッドを、子に渡ってきた時に追加したい
環境
- React: 17.0.2
- Next: 11.1.3
- @chakra-ui/react: ^1.8.5
サンプルコード
親Component
import { CommonForm } from 'components/commonForm';
interface Props {
email: string;
}
export const ParentComponent = ({ email }: Props) => {
return (
// 省略
{/* Container へ渡す children は 共通Component */}
<HogeContainer email={email}>
{/* この時のpropsは1つだけ */}
<CommonForm email={email} />
</HogeContainer>
);
};
子Component
import { Container } from '@chakra-ui/react';
import { cloneElement, ReactElement } from 'react';
interface Props {
email: string;
children: ReactNode;
}
export const Container = ({ email, children }: Props) => {
// 省略
const changeTitle = () => {
// 処理
}
// children(共通Component) へ追加したい props を定義
const additionalProps = { onCompleted: changeTitle };
// cloneElement で children へ props を追加する
const clonedForm = cloneElement(children as ReactElement, {
...additionalProps,
});
return (
<Container>
{/* props が追加された children(共通Component) */}
<>{clonedForm}</>
</Container>
);
};
共通Component(children)
import { Box } from '@chakra-ui/react';
import { useState } from 'react';
import { Controller, useForm } from 'react-hook-form';
import { FormInputData } from './types';
interface Props {
email: string;
onCompleted?: () => void;
}
export const CommonForm = ({ email, onCompleted}: Props) => {
const [isLoading, setIsLoading] = useState(false);
const [message, setMessage] = useState('');
const { registrationHandler } = useRegistration(role, token);
const onSubmit = async (data: FormInputData) => {
setIsLoading(true);
const response = await someHandler(data).finally(() => {
setIsLoading(false);
});
// 省略
onCompleted!();
};
const {
handleSubmit,
control,
formState: { errors },
} = useForm<FormInputData>({
// 省略
});
return (
<form onSubmit={handleSubmit(onSubmit)} noValidate>
// 省略
<Box>
<Button type={'submit'} isLoading={isLoading}>
登録
</Button>
</Box>
</form>
);
};
参考文献