例で使用可能なPrivateRoute https://reacttraining.com/react-router/web/example/auth-workflow は、Reduxに接続した後に機能しません。
私のPrivateRouteは元のバージョンとほとんど同じように見えますが、Reduxにのみ接続され、元の例ではfakeAuthの代わりにそれを使用しました。
const PrivateRoute = ({ component: Component, auth, ...rest }) => (
<Route
{...rest}
render={props =>
auth.isAuthenticated
? <Component {...props} />
: <Redirect to={{ pathname: "/login" }} />}
/>
);
PrivateRoute.propTypes = {
auth: PropTypes.object.isRequired,
component: PropTypes.func.isRequired
}
const mapStateToProps = (state, ownProps) => {
return {
auth: state.auth
}
};
export default connect(mapStateToProps)(PrivateRoute);
使用方法と結果:-
<PrivateRoute path="/member" component={MemberPage} />
<PrivateRoute path="/member" component={MemberPage} auth={auth} />
<PrivateRoute path="/member" component={MemberPage} anyprop={{a:1}} />
react-reduxトラブルシューティングセクション で説明されているように、@ Tharakaの回答を補完して{pure: false}
をconnect
メソッドに渡すことができます。
React-reduxは、shouldComponentUpdate
フック内の小道具の浅い比較を行い、不要な再レンダリングを回避します。コンテキストプロップが変更された場合(react-router)、それはチェックされず、何も変更されていないと想定します。
{ pure:false }
は、この浅い比較を無効にするだけです。
react-router documentation によると、connect
関数をwithRouter
でラップするだけです:
// before
export default connect(mapStateToProps)(Something)
// after
import { withRouter } from 'react-router-dom'
export default withRouter(connect(mapStateToProps)(Something))
これでうまくいきました。
これはreact-reduxの既知の問題であり、この詳細については here を参照してください。問題はconnect
です。HoCはshouldComponentUpdate
を実装しているため、props
が変更されていない場合、ラップされたコンポーネントは再レンダリングされません。 react-routerはコンテキストを使用してルートの変更を渡すため、ラップされたコンポーネントはルートが変更されても再レンダリングされません。しかし、5.1バージョンのreact-reduxで remove shouldComponentUpdate
を実行するようです。現在、回避策として、ルーター内からthis.props.match.params
などのプロップを接続された子コンポーネントに渡しますが、内部では使用しません。ただし、ルートが変更されるたびにコンポーネントが再レンダリングされます。