redux-formのstoreにコンポーネント内でアクセスする
redux-formを使用しててコンポーネント内でredux-form内のstoreの値を得たい時に調べるのにちょっと時間が取られたのでその時のメモ。 したいこと
redux-formを使っている周辺のコンポーネント内で、formに入力されている内容を見たい。
code:tsx
class PostForm extends React.Component<{}, {}> {
render() {
console.log(value) // こことか
return (
<form>
// ↓①ここで入力した内容を
<Field
name="name"
component="input"
type="text"
/>
<div>name: {value}</div> // 入力した内容を表示したい
<ChildHoge
nameValue={value} // 子に渡したい
/>
</form>
);
}
}
redux-formを使うと入力されたデータは自分で定義した唯一のstoreとは別の場所に保存されるので、普通にその自作のstoreにアクセスする方法だけでは見ることができない。
解決策
以下のissueに解決策があった。
コードは以下のようになる。
code:tsx
type Props = {
formState: any;
} & InjectedFormProps;
class PostForm extends React.Component<Props, {}> {
render() {
const formState = this.props.formState; // これでアクセスできる
const value = formState.values.name;
return (
<form>
<Field name="name" component="input" type="text" />
<div>name: {value}</div>
</form>
);
}
}
const mapStateToProps = (state: any) => ({
formState: state.form.postForm // <== こいつを書く
});
export default connect(mapStateToProps)(
reduxForm<{}, Props>({
form: 'postForm'
})(PostForm)
);
redux-formのstoreとconnectし、そこにmapStateToProps関数を挟むことで、いつものようにstateをpropsとしてアクセスすることができるようになる。
注意点
結論は前述した通りだが、少しだけ注意点。reduxに慣れてる人に取っては杞憂な内容だが、上のコードをただコピペするだけでは動かないかもしれない。というのも、そのreduxプロジェクトに依存する点があるからだ。
code:ts
const mapStateToProps = (state: any) => ({
formState: state.form.postForm
// ↑ ②reduxForm()内で指定したプロジェクト内でユニークなform名
// ↑ ①storeでredux-formの名前として登録した名前
});
①に関しては、そのプロジェクトのstore内で以下のように登録していると思うので、そこの名前を指定する。
code:tsx
import { reducer as formReducer } from 'redux-form';
export const configureStore = (): Store =>
createStore(
combineReducers({
reducer,
form: formReducer // ←こいつの名前
})
);
②に関しては、さっきのコードの下部で書いたプロジェクト内でユニークになるformの名前を指定する。
code:tsx
export default connect(mapStateToProps)(
reduxForm<{}, Props>({
form: 'postForm' // ←こいつの名前
})(PostForm)
);