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

Posted

技术标签:

【中文标题】如何将动作传递给 redux 中的组件【英文标题】:How to pass actions down to the components in redux 【发布时间】:2017-04-05 15:41:40 【问题描述】:

我想在我的组件中触发一个动作。这是一个表示组件,不需要了解 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>
                );
            
        )  
    
)

action-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":"***"

      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) 

导出默认连接(mapStateToProps, mapDispatchToProps)(MainLayout) 我收到调度不是功能错误。错误语句实际上听起来像是***中的重复问题,但我也想知道我使用mapDispatchToProps的目的也是正确的。提前致谢。

【问题讨论】:

您在哪个部分 od 代码上收到此错误? @JaganathanBantheswaran:我在 mapDispatchToProps 函数中以及在触发操作后收到此错误。除了错误,我想知道当我应该在使用 redux 路由器时在表示组件中使用操作时我应该做什么。 【参考方案1】:

据我了解,您正在使用export default connect(mapStateToProps, mapDispatchToProps)(MainLayout) 并尝试在MainLayout 中调用dispatch

所以从 react-redux 文档中,如果你看到你可以通过以下方式调用 connect:-

connect()(//Component) --> dispatch 将作为 props 传递 connect(mapStateToProps)(//Component) --> dispatch 将作为 props 传递 connect(mapStateToProps,mapDispatchToProps)(//Component) --> dispatch 不会作为 props 传递给您的组件

在场景 3 中,这种行为是这样的,因为 mapDispatchToProps 已经可以访问调度函数。所以你可以绑定你的函数以在mapDispatchToProps 中调度,然后将此函数传递给你的组件。

示例

您要调度的函数是dispatchMe()dispatchMe2(),它们调用了一个名为dispatchAction 的操作。所以你的mapDispatchToProps 会是这样的:-

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

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

您可以阅读here 了解更多信息

【讨论】:

感谢您的回复。基本上我会在我的 Employee 组件中使用动作“displayPersonalInformation”,它是一个表示组件,因此不支持 redux。为此,您建议我将其条目放入 mapDispatchToProps(如您所示)并可以访问它。现在我试图让它通用。如果我想在演示组件中使用任何动作,那么我必须在我的 mapDispatchToProps 中有那个动作条目。如果我错了,请纠正我。 是的,应该这样做。理想情况下,您应该创建一个EmployeeContainer 并将mapDispatchToProps 作为道具从您的容器传递给您的Employee 组件。 那么 mapDispatchToProps 的外观如何?因为我将有一组可能在该组件中使用的动作创建器。每个动作创建者在 mapDispatchToProps 中有一个单独的条目吗?再次总结一下,“bindActionCreators”永远不会在 mapDispatchToProps 中使用。 @Harikirat,在将 mapDispatchToProps 放入我的连接函数后,我仍然在 bindActionCreators.js 文件中收到错误“显示不是函数”。 你能分享你的代码一次吗?我正在更新多个调度操作的答案【参考方案2】:

由于您使用了bindActionCreators,所以redux 将在您调用动作创建者时dispatch 动作,即在您的情况下为displayPersonalInformation

正如@Harkirat Saluja 在他的回答中提到的那样,如果您使用了mapDispatchToProps,那么您的组件将不会具有与props 绑定的dispatch 函数。

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

function mapDispatchToProps(dispatch) 
   return  dispatch, ...actions: bindActionCreators( actionCreators , dispatch) 

【讨论】:

感谢您的回复。我可以在 redux 中完全不将我的行为与道具联系起来吗?因为那是我的核心问题。如果我听起来很傻,请原谅我。 按照 Harikirat 所说,将 mapDispatchToProps 放入我的连接函数后,我仍然在 bindActionCreators.js 文件中收到错误“显示不是函数”。 当您已经在 mapDispatchToProps 中拥有绑定调度道具时,我无法理解您为什么要绑定调度道具。 @HarkiratSaluja 如果你想拥有dispatchprops 的功能(不是最佳实践),那么你可以像我展示的那样拥有它。仔细阅读我的答案 @Harkirat:对,我不需要。【参考方案3】:
  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);

【讨论】:

【参考方案4】:

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

const mapDispatchToProps = (dispatch) => 
    return bindActionCreators(actionCreators, dispatch);
;

export default connect(null, mapDispatchToProps)(MainLayout);

【讨论】:

【参考方案5】:
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);

【讨论】:

以上是关于如何将动作传递给 redux 中的组件的主要内容,如果未能解决你的问题,请参考以下文章

React/Redux - 将变量传递给动作

使用 props 将 Redux Action 传递给子组件

React Native Redux:动作分派,返回结果

如何响应 redux 中的状态变化并派发另一个动作?

Redux - reducer 与动作的关系

如何使用 Redux connect 中的操作对测试组件进行快照?