如何在React Redux中分别更改列表项的每个状态?

时间:2018-08-14 04:05:44

标签: reactjs react-native redux redux-actions

  

使用

     

react-redux

     

redux-persist

     

redux-actions

     

本机

我正在自己学习react-redux和react-native。 我现在正在尝试从react-redux中的列表更新单个项目。 我的项目中有很多类别和商店。 用户将选择一个类别,然后单击商店列表中一项的“赞按钮”。 就像instagram或facebook。

当我更改一个商品的状态时,商店列表中每个商品的状态会同时更改。

我不知道为什么会这样。

我将结构设置为ducks模式,以避免在更改状态时更改太多文件。 如果有人提出建议,我将不胜感激,这可能对我有所帮助。谢谢。 我看到一些文章来解决此问题,必须提供ID来区分项目并使有效负载成为对象。我不太了解,所以我的代码现在很乱。但是我想知道我的代码会发生什么,所以我分享了我的代码。


restaurantContainer.js

class RestaurantListContainer extends Component {
    shouldComponentUpdate(nextProps) {
        return nextProps.imgUrls !== this.props.imgUrls;
}

componentDidMount() {
    const {category, StoreActions} = this.props;

    try {
        StoreActions.fetchStoreInfo(category);
        StoreActions.fetchImgUrl(category);
        this.getUid();
    } catch (e) {
        console.log(e);
    }
}

async getUid() {
    const {StoreActions} = this.props;
    const uid = await storage.getItem('uid');
    StoreActions.fetchLikeList(uid);
}

render() {
    const {fetching, tabColor, tabName, category, categoryId, navigation, stores, imgUrls, like} = this.props;
    const {onClick} = this;

    return (
        <View>
            ...

            <ScrollView>
                {
                    fetching ?
                        <View>
                            <Bars size={30} color="#40D59B"/>
                        </View>
                        :
                        stores.map((store, i) =>
                            <View key={`item-${i}`}>
                                <RestaurantItem
                                    key={`restaurantItem-${i}`}
                                    i={i}
                                    category={category}
                                    navigation={navigation}
                                    storeInfo={store}
                                    imgUrls={imgUrls[i]}
                                    categoryId={categoryId}
                                    like={like}
                                />
                            </View>
                        )
                }
            </ScrollView>
        </View>
    );
}
}

export default connect(
({styleMod, storeMod}) => ({
    stores: storeMod.stores,
    imgUrls: storeMod.imgUrls,
    fetching: storeMod.fetching,
    likeList: storeMod.likeList
}),
(dispatch) => ({
    StoreActions: bindActionCreators(storeActions, dispatch),
})
)(RestaurantListContainer);

restaurantItem.js

class RestaurantItem extends Component {
pressFunc = (item) => {
    const {navigation} = this.props;
    const {push} = navigation;

    console.log(item.name);

    push('RestaurantDetail', {info: item});
}

voteAdder = async (storeName) => {
    const uid = await storage.getItem('uid');
    const {i, categoryId} = this.props;

    if (uid) {
        const {VoteActions, LikeActions, category, favoriteStores} = this.props;

        try {
            VoteActions.voteAdd(favoriteStores, category, storeName, uid);
            LikeActions.likeClicked(storeName, category, categoryId, i);
        } catch (e) {
            console.log(e);
        }
    } else {
        alert('You are not authorized!');
    }
}

render() {
    const {i, storeInfo, category, categoryId, imgUrls, favoriteStores, like} = this.props;

    return (
        <View style={restaurantCard}>
            <StoreImg
                img={imgUrls}
                name={storeInfo.name}
            />
            <StoreInfoBlock
                i={i}
                storeInfo={storeInfo}
                pressFunc={this.pressFunc}
            />
            <View style={{flexDirection: 'column'}} >
                {
                        <ThumbImg
                            voteAdder={() => this.voteAdder(storeInfo.name)}
                            name={storeInfo.name}
                            favoriteStore={favoriteStores[category]}
                            category={category}
                            like={like}
                            categoryId={categoryId}
                        />
                }
                <Score count={storeInfo.count}/>
            </View>
        </View>
    );
}
}


export default connect(
({voterMod, likeMod}) => ({
    favoriteStores: voterMod.favoriteStores,
    like: likeMod.like,
}),
(dispatch) => ({
    VoteActions: bindActionCreators(voteActions, dispatch),
    LikeActions: bindActionCreators(likeActions, dispatch),
})
)(RestaurantItem);

thumbImg.js

export default class ThumbImg extends Component {
onClick = () => {
    this.props.voteAdder();
}

onFlag = () => {
    const {like, categoryId, i} = this.props;
        if(like.categoryById[categoryId]) {
            if(like.storeById[i]) {
                console.log(2);
                return (
                    <FastImage
                        resizeMode={FastImage.resizeMode.cover}
                        style={{width: 50, height: 50}}
                        source={require('...')}
                    />
                );
            } else {
                return (
                    <FastImage
                        resizeMode={FastImage.resizeMode.cover}
                        style={{width: 50, height: 50}}
                        source={require('...')}
                    />
                );
            }
        } else {
            return (
                <FastImage
                    resizeMode={FastImage.resizeMode.cover}
                    style={{width: 50, height: 50}}
                    source={require('...')}
                />
            );
        }
}

render() {
    return (
        <TouchableOpacity onPress={this.onClick}>
            <View style={{paddingTop: 15, paddingRight: 15}}>
                {
                    this.onFlag()
                }
            </View>
        </TouchableOpacity>
    );
}
}

likeMod.js

// Action types
const ON_LIKE = 'like/ON_LIKE';
const OFF_LIKE = 'like/OFF_LIKE';
// action creator
export const likeClicked = (store, category, categoryId, i) => (dispatch) => {
const selectedCategory = {categoryById: {}};
const categoryInfo = {
    id: categoryId,
    name: category,
};

selectedCategory.categoryById[categoryId] = categoryInfo;

const selectedStore = {storeById: {}};
const storeInfo = {
    id: i,
    name: store
}

selectedStore.storeById[i] = storeInfo;

const favorites = {
    ...selectedCategory,
    ...selectedStore
}

dispatch({type: ON_LIKE, payload: favorites});
}

const initialState = {
like: {
    categoryById: {},
    storeById: {}
}
};

// Reducer
export default handleActions({
[ON_LIKE]: (state, action) => ({...state, like: action.payload}),
[OFF_LIKE]: (state, action) => ({...state, like: action.payload}),
}, initialState);

0 个答案:

没有答案