反应路由器 - 无法传递存储
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);
【讨论】:
以上是关于反应路由器 - 无法传递存储的主要内容,如果未能解决你的问题,请参考以下文章