React Router / Redux / HOC无法使用'render'prop

时间:2017-09-07 06:19:29

标签: reactjs react-router react-redux react-router-v4 higher-order-components

我正在使用反应路由器v4,我正试图围绕反应路由器/ redux / HOC相关问题。我有一个更高阶的组件工作。 HOC本身是connect() - 对于redux商店。如果我通过<Route />道具在component中将其连线:<Route path="/profile" component={ withAuth(Profile) } />可以正常工作,这种方法非常有效。

但是,当我尝试使用<Route />和渲染道具时,它工作:<Route path="/profile" render={ () => withAuth(Profile) } />控制台抛出“Route.render(): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.”当我省略HOC时它确实有效:<Route path="/profile" render={ () => <Profile /> } />因此我怀疑HOC存在问题,但我找不到它。

我尝试使用render的原因是我想将其他道具传递给HOC。除此之外,我发现我无法找到错误。

任何有新鲜眼光的人都可以看看并把我放在正确的道路上吗?谢谢!

/* === app.js === */

import React, { Component } from 'react';
import { Route } from 'react-router-dom';
import { Provider } from 'react-redux';

import Header from './header';
import Home from './home';
import Content from './about';
import Profile from './profile';
import withAuth from './withAuth';

import store from '../reducers/store';

export default class App extends Component {
    render() {
        return (
            <Provider store={store}>
                <div className="mdl-grid">
                    <Header />
                    <main className="mdl-layout__content">
                        <div className="page-content">
                            <Route path="/" exact component={Home} />
                            <Route path="/about" component={Content} />
                            <Route path="/profile" render={ () => withAuth(Profile) } />
                        </div>
                    </main>
                </div>
            </Provider>
        )
    }
}



/* === withAuth.js (Higher order component) === */

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Redirect } from 'react-router-dom';

const HOC = WrappedComponent => {
    return class extends Component {
        render() {
            if (this.props.auth) {
                return <WrappedComponent authenticated={this.props.auth} {...this.props} />
            } else {
                return <Redirect to="/" />
            }
        }
    }
}

function mapStateToProps({ auth }) {
    return { auth };
}

export default WrappedComponent => connect(mapStateToProps)( HOC(WrappedComponent) );

2 个答案:

答案 0 :(得分:1)

它不起作用的原因是因为,这里

<Route path="/profile" render={ () => withAuth(Profile) } />
实际上,

render分配了一个函数withAuth而不是返回值。你需要做的是

const AuthProfile = withAuth(Profile);

export default class App extends Component {
    render() {
        return (
            <Provider store={store}>
                <div className="mdl-grid">
                    <Header />
                    <main className="mdl-layout__content">
                        <div className="page-content">
                            <Route path="/" exact component={Home} />
                            <Route path="/about" component={Content} />
                            <Route path="/profile" render={ (props) => <AuthProfile {...props}/> } />
                        </div>
                    </main>
                </div>
            </Provider>
        )
    }
}

之间的区别
render={ () => withAuth(Profile) } 

render={ (props) => <AuthProfile {...props}/> }

在第一种情况下是一个绑定到上下文的箭头函数。而在第二种情况下,它是一个返回组件的函数

答案 1 :(得分:0)

我认为您的问题与使用<Redirect />的方式有关,您必须将其放在<Route />中。看看这个例子:

const PrivateRoute = ({ component: Component, ...rest }) => (
  <Route {...rest} render={props => (
    fakeAuth.isAuthenticated ? (
      <Component {...props}/>
    ) : (
      <Redirect to={{
        pathname: '/login',
        state: { from: props.location }
      }}/>
    )
  )}/>
)