反应路由器 - 无法通过存储

时间:2018-04-03 09:27:03

标签: javascript reactjs redux react-redux react-router-dom

我无法将商店提供给儿童组件。

这个设置是一个以Symfony作为后端的SPA,但这不应该对此有所影响。

Webpack的入口点是文件:

/client/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, applyMiddleware, compose } from 'redux';
import ReduxPromise from 'redux-promise';
import Root from './App';
import registerServiceWorker from './registerServiceWorker';
import reducers from './pages/combine_reducers';

let composeEnhancers = typeof(window) !== 'undefined' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose

const store = createStore(
   reducers,
   composeEnhancers(
      applyMiddleware(ReduxPromise)
   )
)

ReactDOM.render(
     <Root store={store} />
, document.querySelector('#root')
);

registerServiceWorker();

这样的应用程序位于:

/client/App.js

import React from 'react';
import PropTypes from 'prop-types';
import { Provider } from 'react-redux';
import {
  BrowserRouter as Router,
  Route,
  Link,
  Switch
} from 'react-router-dom';

import HomePage from './pages/home/';
import AccountPage from './pages/account/';


const Root = ({ store }) => {
return(
    <Provider store={store}>
            <div className="App">
                <header className="App-header">
                    <h1 className="App-title">Welcome to React</h1>
                </header>
                <Router>
                    <div>
                        <Link to="/account">Account</Link>
                        <Link to="/">Home</Link>
                        <div>
                            <Switch>
                                <Route path="/account" component={AccountPage} />
                                <Route path="/" component={HomePage} />
                            </Switch>
                        </div>
                    </div>
                </Router>
            </div>
</Provider>
)
}


Root.propTypes = {
   store: PropTypes.object.isRequired
}

export default Root;

到目前为止一切顺利。该商店在App.js中可用。 但事实并非如此。正如您所看到的,我尝试使用connect()创建商店。

/client/pages/home/index.js

import React from 'react';
import { connect } from 'react-redux';
import Register from '../common/register/';
import PropTypes from 'prop-types';

class Home extends React.Component {
   constructor(props){
     super(props)
     console.log(props);
   }

    render() {
        return (
            <div>
                <h1> Hello World from home! </h1>
                <Register />
            </div>
        );
    }
}

Home.propTypes = {
   store: PropTypes.object.isRequired
}

const mapStateToProps = (state) => {
   return {
        store: state.store,
   }
}


export default connect(mapStateToProps)(Home)

在较低级别,注册组件,我能够提交表单,但商店不可用,我无法捕获来自服务器的响应。

/client/pages/common/register/index.js

import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import RegisterForm from './containers/register';
import { actionSubmitRegister } from './actions/';
import PropTypes from 'prop-types';

class Register extends React.Component{
    constructor (props) {
        super(props);
        this.state = {
           registerResponse: '',
        }
        this.onSubmitRegister = this.onSubmitRegister.bind(this);
    }

onSubmitRegister (event) {
    event.preventDefault();
    let submitForm = new Promise((resolve, reject) => {
        actionSubmitRegister(this.props.form.RegisterForm.values);
    });
    submitForm.then((response) => {
        console.log('response',response);
        this.setState({registerResponse:     this.props.submit_register.data});
        console.log('registerResponse', this.state.registerResponse);
    }).catch((error) => {
        console.log(error);
    });
}

render(){           
    return (
        <div>
            <div>
                <RegisterForm
                    submitRegister={this.onSubmitRegister}
                />
                <h3>{this.state.registerResponse}</h3>
            </div>
        </div>
        )
}
}
/*
Register.propTypes = {
    store: PropTypes.object.isRequired
}
*/
const mapStateToProps = (state) => {
    return {
        form: state.form,
        submit_register: state.submit_register,
    }
}

function mapDispatchToProps(dispatch){
    return bindActionCreators({actionSubmitRegister}, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(Register);

3 个答案:

答案 0 :(得分:2)

mapStateToProps中映射store: state.store,但一般情况下,您使用此方法将单个道具从您的状态映射到组件中的道具,而不是映射整个商店(如果可能的话)。 例如:

form: state.form

答案 1 :(得分:0)

您无法访问道具中的商店对象的原因是因为您没有通过道具传递它。 来自react-redux库的提供程序使元素树中的所有子项都可以使用它。商店通过React的上下文API提供,而不是通过道具。

&#34; Context旨在共享可被视为React组件树的“全局”数据。&#34;

因此,在Provider的子组件中,我们现在可以执行类似

的操作
render() {
 const { store } = this.context;
 console.log(store)
 return(
 ...
 )
}

这与react-redux的连接HOC能够访问商店以及随后mapStateToProps或使用商店的调度方法mapDispatchToProps的方式相同。

我认为Provider要求它的子元素是React组件。 请查看此tutorial以获得更深入的解释。

答案 2 :(得分:0)

在我上面收到的输入之后,我查看了我的代码并开始工作。

实际上主要问题是在/client/pages/common/register/index.js文件中,但是我发布了整个链以供参考:

  

/client/index.js

无需改变

  

/client/App.js

对propTypes的引用似乎没有必要,所以我把它们拿出来了。

import React from 'react';
import { Provider } from 'react-redux';
import {
  BrowserRouter as Router,
  Route,
 Link,
 Switch
} from 'react-router-dom';

import HomePage from './pages/home/';
import AccountPage from './pages/account/';


const Root = ({ store }) => {
    return(
        <Provider store={store}>
            <div className="App">
                <header className="App-header">
                    <h1 className="App-title">Welcome to React</h1>
                </header>
                <Router>
                    <div>
                        <Link to="/account">Account</Link>
                        <Link to="/">Home</Link>
                        <div>
                            <Switch>
                                <Route path="/account" component={AccountPage} />
                                <Route path="/" component={HomePage} />
                            </Switch>
                        </div>
                    </div>
                </Router>
            </div>
    </Provider>
    )
}

export default Root;
  

/client/pages/home/index.js

这里似乎不需要propTypes和connect()。

import React from 'react';
import Register from '../common/register/';

class Home extends React.Component {
    constructor(props){
        super(props)
    }

    render() {
        return (
            <div>
                <h1> Hello World from home! </h1>
                <Register />
            </div>
        );
    }
}

export default Home;
  

/client/pages/common/register/index.js

这里的主要问题是onSubmitRegister()方法。承诺未正确设置,我直接引用该操作而不是使用this.props。 React似乎不喜欢那样。

import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import RegisterForm from './containers/register';
import { actionSubmitRegister } from './actions/';

class Register extends React.Component{
    constructor (props) {
        super(props);
        this.state = {
            registerResponse: '',
        }
        this.onSubmitRegister = this.onSubmitRegister.bind(this);
    }

onSubmitRegister (event) {
    event.preventDefault();
    let submitForm = new Promise((resolve) => {
        resolve(this.props.actionSubmitRegister(this.props.form.RegisterForm.values));
    });
    submitForm.then((result) => {
        let data = result.payload.data;
        this.setState({registerResponse: data.message});
    }).catch((error) => {
        console.log(error);
    });
}

render(){           
    return (
        <div>
            <div>
                <RegisterForm
                    submitRegister={this.onSubmitRegister}
                />
                <h3>{this.state.registerResponse}</h3>
            </div>
        </div>
        )
}
}

const mapStateToProps = (state) => {
    return {
        form: state.form,
        submit_register: state.submit_register,
    }
}

function mapDispatchToProps(dispatch){
    return bindActionCreators({actionSubmitRegister}, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(Register);