简体   繁体   English

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

[英]How do I access a function that is being updated from a redux store properly?

I have this component that I split for easy management. 我将这个组件拆分以便于管理。 Before splitting everything worked as expected, after splitting I am getting an error when I click on an icon which calls the createReactionsIcon . 在拆分之前,一切工作均按预期方式进行,拆分之后,单击名为createReactionsIcon的图标时出现错误。 Error says 错误说

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}

How can I access this correctly from my Home component where updateReaction is returning updateReaction from the redux store. 我怎样才能正确地从我访问该Home ,其中组分updateReaction将返回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 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);

Pass your function to component as props , 将功能作为props传递给组件,

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

Now you can use this in your child component, 现在,您可以在子组件中使用它,

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

You can pass the updateReaction from your parent to child as a callback 您可以将updateReaction从您的父母传递给孩子作为回调

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

And you can access it in the child using props.hanldeReaction 您可以使用props.hanldeReaction在子级中访问它

    <Card actions={createReactionsIcon(item, this.props.hanldeReaction)}

You have to pass down the updateReaction() event-handler you defined in Home as a prop to SingleUpload . 您必须传递您在Home中定义的updateReaction()事件处理程序,以作为SingleUpload的道具。 Then you can access that prop from anywhere inside your component. 然后,您可以从组件内部的任何位置访问该道具。

Which means we can cleanup the actions prop inside the Card since we only need to pass the item now. 这意味着我们可以清理Card中的action道具,因为我们现在只需要传递物品即可。

<Card actions={createReactionsIcon(item)}

As well as createReactionsIcon , now we just call that prop directly inside the function createReactionsIcon ,现在我们直接在函数内部调用该prop

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}
        />
    ));
}

Less redundant code overall which sounds like what you are trying to achieve. 总体上减少了冗余代码,这听起来像您想要实现的目标。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM