如何访问从Redux存储正确更新的功能?

时间:2019-05-20 06:49:09

标签: javascript reactjs redux

我将这个组件拆分为便于管理的组件。在拆分之前,一切工作均按预期进行,拆分后,单击名为createReactionsIcon的图标时出现错误。错误说

TypeError: updateReaction is not a function
onClick
./components/home/components/SingleUpload.jsx:26
  23 | 
  24 |    return icons.map(({ key, text, type }) => (
  25 |        <IconText
> 26 |            onClick={() => updateReaction(item.id, key)}
     | ^  27 |            key={key}
  28 |            type={type}
  29 |            text={text}

如何从我的Home组件(其中updateReaction从redux存储返回updateReaction)正确访问此内容。

SubComponent

import PropTypes from 'prop-types';
import React from 'react';
import { Avatar, Card, Icon, List } from 'antd';

import { LIST_TEXTS, STYLES } from '../constants';

const { AVATAR, CARD_CONTAINER, CARD_LIST, ICON, USER_LIST } = STYLES;
const { INNER, MORE, UPLOAD, VERTICAL } = LIST_TEXTS;

const IconText = ({ type, text, onClick }) => (
    <span>
        <Icon type={type} style={ICON} onClick={onClick} />
        {text}
    </span>
);
function createReactionsIcon(item, updateReaction) {
    const { like, dislike, maybe } = item.reactions;
    const icons = [
        { key: 'like', text: `${like.count}`, type: 'heart' },
        { key: 'dislike', text: `${dislike.count}`, type: 'dislike' },
        { key: 'maybe', text: `${maybe.count}`, type: 'meh' },
    ];

    return icons.map(({ key, text, type }) => (
        <IconText
            onClick={() => updateReaction(item.id, key)}
            key={key}
            type={type}
            text={text}
        />
    ));
}

export default class SingleUpload extends React.Component {
    render() {
        const { values } = this.props;

        return (
            <div style={CARD_CONTAINER}>
                <List
                    itemLayout={VERTICAL}
                    dataSource={values}
                    renderItem={item => {
                        const { avatar, description, id, uploader: { image, name } } = item;

                        return (
                            <List.Item style={USER_LIST}>
                                <Card
                                    actions={createReactionsIcon(item, this.updateReaction)}
                                    cover={<img alt={UPLOAD} src={image} />}
                                    extra={<Icon type={MORE} />}
                                    hoverable
                                    key={id}
                                    title={(
                                        <a href="/">
                                            <Avatar src={avatar} style={AVATAR} />
                                            {name}
                                        </a>
                                )}
                                    type={INNER}
                                    style={CARD_LIST}
                                >
                                    {description}
                                </Card>
                            </List.Item>
                        );
                    }}
                />
            </div>
        );
    }
}

Home.js

import PropTypes from 'prop-types';
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';

import SingleUpload from './SingleUpload';
import ComparisonUpload from './ComparisonUpload';
import { STYLES } from '../constants';
import * as actions from '../actions';
import { getUploads } from '../selectors';

const { CARD_CONTAINER } = STYLES;

class Home extends React.Component {
    componentDidMount() {
        const { actions: { requestUploadList } } = this.props;

        requestUploadList();
    }

    updateReaction = (id, reaction) => {
        const { actions: { updateReaction } } = this.props;
        const payload = { id, reaction };
        updateReaction(payload);
    }

    render() {
        const { uploads } = this.props;

        return (
            <div style={CARD_CONTAINER}>
                <SingleUpload values={[...uploads.values()]} />
                <ComparisonUpload values={[...uploads.values()]} />
            </div>
        );
    }
}

Home.propTypes = {
    actions: PropTypes.objectOf(PropTypes.object),
    uploads: PropTypes.instanceOf(Map),
};

const mapStateToProps = state => ({
    uploads: getUploads(state),
});

const mapDispatchToProps = dispatch => ({
    actions: bindActionCreators(actions, dispatch),
});

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

3 个答案:

答案 0 :(得分:3)

props的形式将函数传递给组件,

<SingleUpload values={[...uploads.values()]} updateReaction = {this.updateReaction}/>

现在您可以在子组件中使用它,

<IconText onClick={() => this.props.updateReaction(item.id, key)}

答案 1 :(得分:2)

您可以将updateReaction从您的父母那里传递给孩子作为回叫

<SingleUpload values={[...uploads.values()]} hanldeReaction={this.updateReaction} />

您可以使用props.hanldeReaction

在子级中访问它
    <Card actions={createReactionsIcon(item, this.props.hanldeReaction)}

答案 2 :(得分:2)

您必须传递在Home中定义为updateReaction()的道具的SingleUpload事件处理程序。然后,您可以从组件内部的任何位置访问该道具。

这意味着我们可以清理卡片中的动作道具,因为我们现在只需要传递物品即可。

<Card actions={createReactionsIcon(item)}

createReactionsIcon一样,现在我们直接在函数内部调用该道具

function createReactionsIcon(item) {
    const { like, dislike, maybe } = item.reactions;
    const icons = [
        { key: 'like', text: `${like.count}`, type: 'heart' },
        { key: 'dislike', text: `${dislike.count}`, type: 'dislike' },
        { key: 'maybe', text: `${maybe.count}`, type: 'meh' },
    ];

    return icons.map(({ key, text, type }) => (
        <IconText
            onClick={() => this.props.updateReaction(item.id, key)}
            key={key}
            type={type}
            text={text}
        />
    ));
}

总体上减少了冗余代码,听起来像您要实现的目标。