私は別の小さな自転車を共有したい-まず第一に、貴重なアドバイスを得るために。 追加の例は、GitHubファンプロジェクトのソースコードにあります 。
プロジェクトのほとんどすべてのページは、ページコンポーネントによってラップされます。
const MyPage = () => ( <Page> Hello World </Page> )
外部データをロードするために、ページコンポーネントには3つの渡されたプロパティ(プロパティ)があります。
- onMountedコールバック関数は、componentDidMountコンポーネントライフサイクルメソッド内で呼び出されます。 Reactのドキュメントによると、この場所で外部データをダウンロードすることをお勧めします。
- 外部データをロードする前に渡すisLoadingフラグはtrueで、この操作が完了した後はfalseです。
- 外部データのロードが失敗した場合、isNotFoundフラグを渡します。
Reduxの例:
// components/Post/PostViewPage.js const PostViewPage = ({ post, ...props }) => ( <Page {...props}> <Post {...post} /> </Page> ) const mapStateToProps = (state) => ({ post: state.postView, isNotFound: isEmpty(state.postView), }) const mapDispatchToProps = (dispatch, ownProps) => ({ onMounted: () => { const id = parseInt(ownProps.match.params.id, 10) dispatch(actions.read(id)) } }) export default connect(mapStateToProps, mapDispatchToProps)(PostViewPage)
isLoadingフラグは、propsに明示的に渡されず、PageコンポーネントのmapStateToPropsを介してバインドされることに注意してください(これについては後で説明します)。
式について質問がある場合:
// - { post, ...props } // {...props}
...次に、MDNディレクトリを参照できます。
副作用actions.read(id)はredux-thunkを提供します:
// ducks/postView.js const read = id => (dispatch) => { // state.app.isLoading dispatch(appActions.setLoading(true)) // state.postView dispatch(reset()) // let isTimeout = false // let isFetch = false setTimeout(() => { isTimeout = true if (isFetch) { dispatch(appActions.setLoading(false)) } }, 500) // state.app.isLoading 500 axios(`/post/${id}`) .then(response => { const post = response.data // state.posts dispatch(postsActions.setPost(post)) // state.postView dispatch(set(post)) }) .catch(error => { dispatch(appActions.setMainError(error.toString())) }) .then(response => { isFetch = true if (isTimeout) { dispatch(appActions.setLoading(false)) } }) }
データのロードが速すぎると、点滅するダウンロードインジケータの不快な視覚効果が発生します。 これを避けるために、500ミリ秒のタイマーとisTimeoutおよびisFetchフラグにロジックを追加しました。
Pageコンポーネントは、他の装飾を破棄する場合、外部データをロードするプロセスを提供します。
// components/Page/Page.js class Page extends React.Component { _isMounted = false componentDidMount() { this._isMounted = true const { onMounted } = this.props if (onMounted !== void 0) { onMounted() } } render() { const { isNotFound, isLoading, children } = this.props if (this._isMounted && !isLoading && isNotFound) { return <NotFound /> } return ( <div> <PageHeader /> <div> {this._isMounted && !isLoading ? children : <div>...</div> } </div> <PageFooter /> </div> ) } } const mapStateToProps = (state, props) => ({ isLoading: state.app.isLoading }) export default connect(mapStateToProps)(Page)
どのように機能しますか? 最初のレンダーパスは、_isMountedフラグをオフにして実行され、ロードインジケーターが表示されます。 次に、 ライフサイクルメソッドcomponentDidMountが実行され、_isMountedフラグがオンになり、onMountedコールバック関数が開始されます。 onMounted内では、副作用(たとえば、actions.read(id))が発生し、state.app.isLoadingフラグが有効になります。これにより、新しいレンダリングが発生します-ロードインジケーターは引き続き表示されます。 副作用内でaxios(またはフェッチ)を非同期に呼び出した後、state.app.isLoadingフラグをオフにします。これにより、新しいレンダーが発生します。ロードインジケーターを表示する代わりに、埋め込みコンポーネント(子)のレンダーが実行されます。 ただし、isNotFoundフラグの組み込みが機能する場合、ネストされたコンポーネント(子)のレンダリングの代わりに、<NotFound />のレンダリングコンポーネントが実行されます。