Redux ReactJS:组件如何访问商店?

时间:2017-12-27 11:42:51

标签: javascript reactjs redux react-redux

为了开始,我看到很多问题在stackoverflow上看起来像我的,但我想我想念一些,这就是我问这个问题的原因。

我的应用中有一个Maincomponent,它使用动作addDatas将数据添加到我的商店。 这部分工作,我可以使用this.props访问我的商店在上下文和MainComponent的子项中。 但是当我去OtherComponent(这是一个基本组件,我只想显示在MainComponent中收集的所有数据)时,我的商店似乎是空的。

当我使用MainComponent时,有人能告诉我我做错了什么以及OtherComponent应该是什么样子来访问我在商店中设置的数据。

感谢。

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './components/App';    
import { Provider } from 'react-redux';
import { createStore } from 'redux';    
import reducer from './reducers'

const store = createStore(reducer);

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);

reducers.js

import { ADD_DATAS } from '../constants';

const reminder = (action) => {
  switch (action.type) {
    case ADD_DATAS:
      return {
        datas: action.datas,
        id: action.id
      };
    default:
      return {
        text: action.text,
        id: action.id
      };
  }

}

const reminders = (state = [], action) => {
  let reminders = null;
  switch (action.type) {
    case ADD_DATAS:
      reminders = [...state, reminder(action)];
      return reminders;
    default:
      return state;
  }
}

export default reminders;

Action.js

import {ADD_DATAS} from '../constants';
// ADD_DATAS = 'ADD_DATAS' in constants

export const addDatas = (text, id) => {
  const action = {
    type: ADD_DATAS,
    datas: text,
    id: id
  }
  return action;
}

App.js

import React, { Component } from 'react'
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'

import RouterComponent from '../Router/RouterComponent';
import OtherComponent from './OtherComponent';
import MainComponent from './MainComponent';

class App extends Component {
  render() {
    return (
        <div className="container-fluid">
          <div className="row">
           <Sidebar />
            <Router>
              <RouterComponent>
                <Switch>
                    <Route exact path="/oth" component={OtherComponent}/>
                    <Route exact path="/main" component={MainComponent}/>
                    <Route exact path="/" component={MainComponent}/>
                </Switch>
              </RouterComponent>
            </Router>
          </div>
        </div>
    );
  }
}

export default App;

MainComponent.js

import React, { Component } from 'react';
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import { addDatas } from '../actions'

class MainComponent extends Component {

  addDataStore(text, id){
    this.props.addDatas(text, id)
  }

  render(){
    return ( .... )
  }
}

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

function mapStateToProps(state){
  return {
    reminders: state
  }
}
export default connect(mapStateToProps, mapDispatchToProps)(MainComponent);

OtherComponent.js

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

class OtherComponent extends Component {
    render(){
       console.log(this.props.reminders)
    }
}

function mapStateToProps(state){
    return {
        reminders: state
    }
}
export default connect(mapStateToProps)(OtherComponent);

Sidebar.js

import React, { Component } from 'react';
import '../css/sidebar.css';

export default class Sidebar extends Component {
  render(){
    return (
      <nav className="col-2 col-md-2 sidebar">
        <div className="sidebar-logo">
          <a href="/main">
            MainComponent
            </div>
          </a>
        </div>
        <ul >
          <li >
            <a href="/main" >
              MainComponent
            </a>
          </li>
          <li >
            <a href="/oth" >
              OtherComponent
            </a>
          </li>
        </ul>
      </nav>
    )
  }
}

5 个答案:

答案 0 :(得分:2)

您应该使用connect HoC将OtherComponent连接到redux存储。

答案 1 :(得分:2)

您也可以使用statuslog HOC连接otherComponent,以便访问connect。一旦组件连接到层次结构中的商店,您就可以将数据作为道具传递给其子项。但是,您确实需要将顶级组件连接到Store

store

答案 2 :(得分:2)

要了解这一点,我们首先需要了解以下代码段

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

我们将mapStateToProps函数传递给我们从react-redux获取的connect方法。那么让我们了解连接是如何工作的以及它实际上的工作

1. It calls your mapStateToProps function and passes the current value of (redux state/ redux store) to the function.
2. Then whatever value is returned by the mapStateToProps function after execution is passed down as props to the mainComponent(in your case).

因此,由于主要组件的子组件没有连接语句,因此道具不可用。 你可以将redux状态作为道具提供两个

1. Passing it down from main component as follows inside mainComponent.js render method we have 

import React, { Component } from 'react';
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import { addDatas } from '../actions'

class MainComponent extends Component {

  addDataStore(text, id){
    this.props.addDatas(text, id)
  }

  render(){
    return (
      <Child1 reminders={this.props.reminders}/*can be accessed as this.props.reminders*//>
      <Child2 reminders={this.props.reminders}/*can be accessed as this.props.reminders*//>   
    )
  }
}

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

function mapStateToProps(state){
  return {
    reminders: state
  }
}
export default connect(mapStateToProps, mapDispatchToProps)(MainComponent);

2.Another way to do this will be using connect Statement inside your child component as well

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

 class Child1 extends Component{
 .....
 
 
 
 
 
 }



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

function mapStateToProps(state){
  return {
    reminders: state
  }
}
export default connect(mapStateToProps, mapDispatchToProps)(Child1);//need to change here must be same as className

答案 3 :(得分:1)

您需要像在MainComponents.js中一样使用mapStateToProps和mapDispatchToProps函数连接其他组件

import React, { Component } from 'react';
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import { addDatas } from '../actions'

class OtherComponent extends Component {
    addDataStore(text, id) {
        this.props.addDatas(text, id)
    }
    render() {
    }
}

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

function mapStateToProps(state) {
    return {
        ...state
    }
}
export default connect(mapStateToProps, mapDispatchToProps)(OtherComponent);

答案 4 :(得分:0)

那么,

我的问题不在于我的Redux实现,而在于我使用href在我的组件之间导航。 问题是我的补充工具栏组件不在路由器组件中,然后我必须将历史记录保存在redux存储中,并使用之前保存的历史记录在我的侧边栏组件中调用history.push。

在我在路由器中的所有组件中添加了构造函数:

constructor(props){
  super(props);
  ...
  this.props.addHistory(props.history);
}

addHistory添加历史记录(如果它尚未存在)。 然后在我的侧边栏中,我使用商店中的历史记录来使用推送功能:

for (var e in this.props.reminders){
  if(this.props.reminders[e].history !== undefined ){
    this.props.reminders[e].history.push('/oth');
  }
}

我不知道这是否是最干净的方法,但它确实有效。