地味だけど、割といいなと思ったTips。
blade側
errors='@json($errors->toArray())'
がポイント。LaravelのValidationで返ってきた内容をjsonに変換している。
defaultValueは、エラー時に元の入力値を保持するために使用。
@extends('layouts.app')
@section('content')
<div id="header"></div>
<form method="POST" action="{{ route('login') }}">
@csrf
<div id="login" errors='@json($errors->toArray())' defaultValue='@json(['email'=>old('email')])'></div>
</form>
<script src="{{mix('js/app.js')}}" ></script>
@endsection
受け取るReactコンポーネント
import * as React from 'react';
import { render } from 'react-dom';
import PasswordField from '../atoms/PasswordField';
import EmailInputField from '../atoms/EmailInputField';
import SubmitButton from '../atoms/SubmitButton';
import { Grid } from '@material-ui/core';
type Props = {
errors?: {
email :string,
password : string
}
defaultValue?: {
email: string
}
}
const Login: React.FC<Props> = ({ errors, defaultValue }) => (
<div>
// 中略
<EmailInputField label="メールアドレス" errors={errors?.email} defaultValue={defaultValue?.email}/>
<PasswordField label="パスワード" errors={errors?.password}/>
<SubmitButton label="LOGIN"/>
// 中略
</div>
);
const Element = document.getElementById('login');
if(Element){
const errors = Element.getAttribute('errors');
const parsedErrors = errors && JSON.parse(errors);
const defaultValue = Element.getAttribute('defaultValue');
const parsedDefaultValue = defaultValue && JSON.parse(defaultValue);
render(<Login errors={parsedErrors} defaultValue={parsedDefaultValue} />,
document.getElementById('login'));
}
bladeから受け取ったjsonをparseしているのはこの処理
あとはコンポーネントに渡してあげるだけ。
const errors = Element.getAttribute('errors');
const parsedErrors = errors && JSON.parse(errors);
エラー描画をするコンポーネント
helperTextはundefined
許容なので、判定なしでerrors
を設定可能。
import React from 'react';
import TextField from '@material-ui/core/TextField';
import { InputAdornment } from '@material-ui/core';
import Mail from '@material-ui/icons/Mail';
type Props = {
label: string;
errors?: string;
defaultValue?: string;
}
const EmailInputField: React.FC<Props> = ({ label , errors , defaultValue }) => (
<div>
<TextField id="email" name="email" label={label}
error={(!!errors)?true:false}
helperText={errors}
defaultValue={defaultValue}
/>
</div>
);
export default EmailInputField;