こういう表示とデータを疎結合にしたときに問題になるのがダイアログ系。
頭をひねった感じこんなのでいけるんじゃないかっていう感じのが出来ました。
コンポーネント
まず、アラートを出すコンポーネントを準備します。UIは持たないrenderメソッドはnullを返すだけのコンポーネントです。特徴は、componentWillReceivePropsでプロパティにメッセージを受け取ったときにalertを出すようにしてるところです。
import * as React from 'react'; interface AlertProps extends React.Props<{}> { message: string; }exportdefaultclass Alert extends React.Component<AlertProps, {}> { componentWillReceiveProps(nextProps: AlertProps) {if (nextProps.message) {alert(nextProps.message); }} render() {returnnull; }; }
アクション
こんなアクションのデータ形式を定義しておいて。
/** * Actionのインターフェース */exportinterface Action<T> { type: string; payload?: T; error?: Error; }
んで、Alert用のアクションのpayloadの型を定義しておいて
exportdefaultclass AlertPayload {static get TYPE() {return'ALERT'; } constructor(public message: string) {}}
アクションクリエイターでアクションを発生させます。このとき、メッセージセットのアクションとメッセージリセットのアクションを2つ連続して呼び出すところがポイントです。2つ連続して呼び出すためにredux-thunkを前提としたアクションになります。
import * as actions from './'; import * as Redux from 'redux'; import AlertPayload from './AlertPayload'; function setAlert(message: string): actions.Action<AlertPayload> {return{ type: AlertPayload.TYPE, payload: new AlertPayload(message) }; }exportfunctionalert(message: string) {return (dispatch: Redux.Dispatch) => { dispatch(setAlert(message)); dispatch(setAlert(null)); }; }
Reducer
Reducerは、素直にメッセージプロパティの書き換えを行います。
import Alert from '../models/Alert'; import * as actions from '../actions'; import AlertPayload from '../actions/AlertPayload'; import assign = require('object-assign'); exportfunctionalert(state = new Alert(), action: actions.Action<any>) {switch (action.type) {case AlertPayload.TYPE: return assign({}, state, { message: (action.payload as AlertPayload).message } as Alert); default: return state; }}
このAlertクラスは、コンポーネントのAlertクラスじゃなくて以下のようなデータの入れ物です。
exportdefaultclass Alert { message: string; }
繋ぐ
connectメソッドで繋いで完成。
import * as React from 'react'; import * as ReactRedux from 'react-redux'; import * as reducers from '../reducers'; import Alert from './Alert'; interface LayoutProps extends React.Props<{}> { userName: string; message: string; }class Layout extends React.Component<LayoutProps, {}> { render() {return ( <div> <Alert message={this.props.message} /> <h1 style={{display: 'inline-block'}}>Redux master detail application sample</h1> {this.props.userName ? <span>ユーザー名:{this.props.userName}</span> : null}<hr /> {this.props.children}</div> ); }}function select(state: reducers.AppState): LayoutProps {return{ userName: state.auth.userName, message: state.alert.message }; }exportdefault ReactRedux.connect(select)(Layout);
stateに変更があるたびにAlertコンポーネントのプロパティに値がセットされてダイアログが出るという感じです。すぐにnullにリセットされるため、別のステートの変更があっても、そのときにはnullになってるので、アラートがつられて出ることはありません。
ソースコード全体
今作ってる別のサンプルプログラムに組み込んじゃってるのでもうちょい待ってください。