反应路由器 - 无法传递存储

Posted

技术标签:

【中文标题】反应路由器 - 无法传递存储【英文标题】:react router - unable to pass store down 【发布时间】:2018-09-12 13:46:26 【问题描述】:

我无法使商店对子组件可用。

设置是一个以 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);

【问题讨论】:

您不需要单独存储变量。 mapStateToProps 中的 state 参数是 store 实例 【参考方案1】:

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

form: state.form

【讨论】:

感谢@Jonathan R,但这似乎不起作用。 register/index.js 上的 mapStateToProps 函数对 submit_register: state.submit_register 执行此操作,但 submit_register 仍然没有收到来自 reducer 的 props。 我接受了您的回答,因为它使我朝着正确的方向前进。我发布了一个修改后的答案以供参考。谢谢【参考方案2】:

您无法访问 props 中的 store 对象的原因是您没有通过 props 传递它。 react-redux 库中的提供程序,使其可供元素树下的所有子级使用。 Store 是通过 React 的 context API 提供的,而不是通过 props。

“上下文旨在共享可被视为 React 组件树的“全局”数据。”

所以在 Provider 的子组件中,我们现在可以做类似的事情

render() 
 const  store  = this.context;
 console.log(store)
 return(
 ...
 )

这与 react-redux 的 connect HOC 能够访问 store 并随后访问 mapStateToProps 或利用 store 的 dispatch 方法访问 mapDispatchToProps 的方式相同。

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

【讨论】:

感谢@Thomas,但我仍然无法在上面的代码中为 console.log 定义。 @BernardA 你可以尝试将提供者标签中的内容更改为 React 组件.....这可能会有所帮助【参考方案3】:

在收到上面的输入后,我检查了我的代码并让它工作。

其实主要问题在 /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);

【讨论】:

以上是关于反应路由器 - 无法传递存储的主要内容,如果未能解决你的问题,请参考以下文章

反应路由器传递数据

反应路由器将变量/状态传递给新路由?

反应路由器参数

使用时反应路由器传递道具[重复]

text 传递道具来反应路由器组件

在 reactJS 中从反应路由器链接传递道具