首页 文章

如何将操作传递给redux中的组件

提问于
浏览
4

我想在我的组件中触发一个动作 . 这是一个演示组件,不需要知道redux . 路由器实现使用react-router-redux完成 .

main.js:

let store = createStore(rootReducer)

const history = syncHistoryWithStore(hashHistory, store)

class RenderClass extends Component {
  render() {
    return (
        <Provider store={store}>
            <Router history={history}>
                <Route path="/" component={MainLayout}>
                    <Route name="employees" path="/employees" url="http://localhost:8080/" component={EmployeeTable}></Route>
                    <Route name="personalInformation" path="/personalInformation/:employeeId" url={URI} component={PersonalInformation} />
                    .....
                </Route>
            <Router>
        </Provider>
        );
    }
}

App.jsx:

import * as Actions from './action-creator';
const MainLayout = React.createClass({
                render: function() {

                    const { dispatch, list } = this.props;
                    let actions = bindActionCreators(Actions, dispatch);
                    console.log(actions);

                    return (
                        <div className="wrapper">
                            <Header actions={actions} list={list} params={this.props.params} />

                    {React.cloneElement(this.props.children, this.props)}
                        </div>
                    )
                }
            }); 

function select(state) {
   return {
      list: state.listingReducer
   }
}
export default connect(select)(MainLayout);

header.js:

define(
    [
        'react',
        'jquery',
        'appMin'
    ],
    function (React, $) {
        var Link = require('reactRouter').Link;
        var Header = React.createClass({
            handleClick: function () {
                //Action called here
                this.props.actions.listEmployees();
            },      
            render: function () {
                return (
                    <ul className="sidebar-menu">
                        <li>
                            <Link to={'/employees'} onClick={this.handleClick}><i className="fa fa-home"></i>Employees</Link> 
                        </li> 
                    </ul>
                );
            }
        });
        return Header;
    }
)

employee.js:

define(
    [
        'react',
        'jquery',
        'appMin'
    ],
    function (React, $) {
        var EmployeeTable = React.createClass({

            render: function () {
                if (this.props.list != undefined) {
                    var listItems = this.props.list.map(function (listItem) {
                        return (
                            <tr key={listItem.id}>
                                <td> {listItem.name}</td>
                <td><Link to={'/personalInformation/' + employee.id} onClick={this.props.actions.displayPersonalInformation(employee.id)}>Personal Information</Link></td>
                                ......
                            </tr>
                        );
                    }, this);   
                    })
                }
                return (
                    <table>
                        <tbody>
                            {listItems}
                        </tbody>                    
                    </table>
                );
            }
        })  
    }
)

行动creator.js:

export function listEmployees() {
    return {
      type: types.LIST_EMPLOYEES
   };
}

export function displayPersonalInformation() {
        return {
          type: types.DISPLAY_PERSONAL_INFORMATION
       };
    }

reducer.js:
function addEmployee(state, action) {

   switch (action.type) {

      case types.LIST_EMPLOYEES:
         return {"id":"1", "name":"Stackoverflow"}

      default:
        return state
   }
}

function listingReducer(state = [], action) {
    switch (action.type) {

        case types.LIST_EMPLOYEES:
            return [
                ...state, 
                addEmployee(undefined, action)
            ]

        case types.DISPLAY_PERSONAL_INFORMATION:
                return // Gets personal Information

        default:
            return state;
    }
}


const rootReducer = combineReducers({
   listingReducer
})

export default rootReducer

道具将不包含动作,因为我没有将它绑定到道具 . 我尝试在 App.js 中编写mapStateToProps和mapDispatchToProps,如下所示:

function mapStateToProps(state) {
   return {
        list: state.list
    }
}

function mapDispatchToProps(dispatch) {
   return { actions: bindActionCreators({ actionCreators }, dispatch) }
}

export default connect(mapStateToProps,mapDispatchToProps)(MainLayout)我收到的调度不是函数错误 . 错误语句实际上听起来像stackoverflow中的重复问题,但我也想知道我使用mapDispatchToProps的目的也是正确的 . 提前致谢 .

5 回答

  • 0
    class MainLayout extends React.component{
          render(){
            console.log(this.props.list);
            return(
                <div>
                   <h1>mainlayout</h1>
                 </div>
                );
            } 
        }
      function mapStateToProps(state) {
           return {
               list: state.listingReducer
           }
       }
       export default connect(mapStateToProps)(MainLayout);
    
  • 0

    您无法通过道具访问您的操作,因为您要将操作分配给操作属性 . 将动作绑定到道具的方式可以通过this.props.actions.myFunction访问您的函数 . 如果您想通过道具直接调用您的操作,请将您的操作连接到道具,如下所示:

    const mapDispatchToProps = (dispatch) => {
        return bindActionCreators(actionCreators, dispatch);
    };
    
    export default connect(null, mapDispatchToProps)(MainLayout);
    
  • 0
    import { bindActionCreators, } from 'redux';
    import { connect, } from 'react-redux';
    
    /**
     * Map redux actions to the Component's props
     * @param {*} dispatch The Redux store's dispatch method
     * @returns {*} Object
     */
    const mapDispatchToProps = (dispatch) => {
        return bindActionCreators({
            yourActions,
        }, dispatch);
    };
    
    export default connect(mapDispatchToProps)(MainLayout);
    
  • 4

    由于您已经使用了 bindActionCreatorsreduxdispatch 在您调用动作创建者时会采取行动,即 displayPersonalInformation .

    正如@Harkirat Saluja在他的回答中提到的,如果你使用了 mapDispatchToProps ,那么你的组件将没有 dispatch 函数与 props 绑定 .

    但是如果你想 dispatchprops (不是最佳实践),那么你可以有类似的东西,

    function mapDispatchToProps(dispatch) {
       return { dispatch, ...actions: bindActionCreators({ actionCreators }, dispatch) }
    }
    
  • 0

    所以根据我的理解,你正在使用 export default connect(mapStateToProps, mapDispatchToProps)(MainLayout) 并尝试在 MainLayout 中调用 dispatch .

    因此,如果您发现您可以通过以下方式调用connect,请参阅react-redux文档:

    • connect()(//Component) - > dispatch将作为道具传递

    • connect(mapStateToProps)(//Component) - > dispatch将作为道具传递

    • connect(mapStateToProps,mapDispatchToProps)(//Component) - > dispatch would not be passed as props to your component

    在方案3中,行为是这样的,因为 mapDispatchToProps 已经可以访问调度功能 . 因此,您可以将函数绑定到 mapDispatchToProps 中,然后将此函数传递给组件 .

    Example

    要分派的函数是 dispatchMe()dispatchMe2() ,它调用一个名为 dispatchAction 的动作 . 所以你的 mapDispatchToProps 会是这样的: -

    function mapDispatchToProps(dispatch){
      return {
         dispatchMe : () => {
           dispatch(dispatchAction()) 
        },
        dispatchMe2 : () => {
          dispatch(dispatchAction2())
        }
      }
    }
    

    现在,在您的组件中,您可以传递 dispatchMe 并在需要时调用它 .

    有关详细信息,请参阅here

相关问题