在反应redux中调用子组件上的动作的惯用方法,而不是一直传递道具

时间:2016-06-02 01:35:31

标签: reactjs typescript redux react-redux

我目前正在学习如何使用react,redux和react-redux,并且需要相当简单。我想渲染类似于以下内容的东西......

--------------------------------
| title 1         |----------| | 
| description 1   | button 1 | |
| desc... cont.   |----------| |
|------------------------------|
| title 2         |----------| | 
| description 2   | button 2 | |
| desc2... cont.  |----------| |
|------------------------------|
| title 3         |----------| | 
| description 3   | button 3 | |
| desc3... cont.  |----------| |
|------------------------------|

这代表Items的列表。每个Item(图中显示的3)都有titledescription。当我点击按钮时,我想为Item执行一些操作,例如显示带有Item's标题的提醒框。

我设法根据Redux Tutorial制作了一份工作样本。我最终得到了一个名为ItemsContainer.tsx的容器(智能)组件和两个名为ItemList.tsx(列表)和Item.tsx(单个项目)的Presentation(哑)组件。它在层次结构中看起来像......

App
-- ItemsContainer
---- ItemList
------ Item
------ Item

然而,像Redux Tutorial一样,这要求我通过props通过每个演示组件传递onClick函数。如果我有一个更深的嵌套,这可能会变得很麻烦,所以我试图找到另一种方式。

我现在拥有两个容器组件ItemListContainer.tsxItemContainer.tsx和两个演示组件ItemList.tsxItem.tsx。但是,每当我点击按钮时,我的警告框就会显示[Object object]。我相信发生的事情是我实际上接收了按钮点击的事件,而不是Item.id,但我不知道从这里去哪里以确保为onClick分配了正确的功能。它在层次结构中看起来像......

App
-- ItemListContainer
---- ItemList
------ ItemContainer
-------- Item
-------- Item

代码如下......

// app.tsx
import * as React from 'react';
import { ItemListContainer } from '../addItem/ItemListContainer';

export const App = () => {
    return <div><ItemListContainer/></div>;
};
// itemListContainer.tsx
import { ItemList } from './itemList';
import { connect } from 'react-redux';


function mapStateToProps(state: any): any {
    return {
        items: state.items
    }
}

export const ItemListContainer = connect(mapStateToProps, null)(ItemList);
// itemList.tsx
import * as React from 'react';
import { IItems, IItemSummary } from '../../data/Items/models/Item';
import { ItemContainer } from './ItemContainer';

export const ItemList = (props: IItems) => {

    let divStyle = {
            position: 'block',
            border: 'solid #aeb0b5 1px',
            overflowY: 'auto',
            overflowX: 'hidden',
            width: 650,
            height: 300
    };

    return (
        <div style={divStyle}>
            {
                props.items.map(function (item: IItemSummary) {
                    return <ItemContainer {...item} />;
                })
            }
        </div>
    );
};
// itemContainer.tsx
import { Item } from './Item';
import { IItems } from '../../data/Items/models/Item';
import { removeItem } from "../../data/Items/actions/initDashboardItems"
import { connect } from 'react-redux';


function mapStateToProps(state: any): any {
    return {
        items: state.items
    };
}


const mapDispatchToProps = (dispatch: any): any => {
    return {
        onClick: (id: any) => {
            alert(id);
        }
    };
};

export const ItemContainer = connect(
    mapStateToProps,
    mapDispatchToProps
)(Item);
// item.tsx
import * as React from 'react';
import { IItemSummary } from '../../data/items/models/item';

export const item = (props: IItemSummary) => {

    let outerDiv = {
            position: 'relative',
            borderBottom: 'solid #aeb0b5 1px',
            width: '650px'
        };

        let textDiv = {
            position: 'relative',
            width: '500px',
            padding: 5
        };

        let buttonDiv = {
            position: 'absolute',
            top: '5px',
            right: '10px',
            padding: 5
        };

    return (
        <div style={outerDiv}>
            <div style={textDiv}><strong>{props.title}</strong></div>
            <div style={textDiv}>{props.description}</div>
            <div style={buttonDiv}><button onClick={props.onClick}>Add Chart</button></div>
        </div>
    );
};

虽然我最终需要解决如何使用React和Redux将正确的函数连接到onclick我还想知道在本文顶部描述的用户界面构建此代码的惯用React Redux方法是什么?< / p>

2 个答案:

答案 0 :(得分:0)

  

如果我有更深的嵌套,这可能会变得很麻烦,所以我试图找到另一种方式

你可以尽可能多地传递道具(使用哑组件)但是在任何时候你都可以自由地创建一个可以放在任何地方的新智能组件(在一个哑组件内或另一个智能组件内)。

答案 1 :(得分:0)

解决onClick布线不正确的问题的解决方法是修改item.tsx文件,如此...

// item.tsx
import * as React from 'react';
import { IItemSummary } from '../../data/items/models/item';

export const item = (props: IItemSummary) => {

    const clickHandler = () => props.onClick(props.title);

    // style stuff omitted for clarity

    return (
        <div style={outerDiv}>
            <div style={textDiv}><strong>{props.title}</strong></div>
            <div style={textDiv}>{props.description}</div>
            <div style={buttonDiv}><button onClick={clickHandler}>Add Chart</button></div>
        </div>
    );
};

引入了显式clickHandler函数,以便props.title可以传递给props.onClick方法。

我仍然不确定这是否是惯用的react-redux,如果找到更合适的方法,可能会更新此答案。

(感谢acemarke和其他人在discordapp.com上的Redux社区频道上寻求帮助)