简体   繁体   中英

Redux with React Native state not updating

I tried to add a recipe to favourites using Redux with React Native. If I use the state in the favicon.js this works fine but does not work with Redux.

This is my favicon.js


    import React, {useState} from 'react'
    import { FontAwesome } from '@expo/vector-icons'
    import { View, TouchableOpacity,StyleSheet, Text, Alert } from 'react-native'
    import { connect } from 'react-redux'
    import { toggleFavId, isFavourite } from '../actions'
    
    const FavIcon = ({recipeid, toggle, isFav, text}) => {
    
      // const [isFavNew, setFavNew] = useState(false)
    
      // const toggleFav = (recipeid) =>{
      //   setFavNew(!isFavNew)
      //   console.log(`Entered toggle ${recipeid} isfavnew = ${isFavNew}`)
      // }
    
       return (
            <View>
                <TouchableOpacity style={styles.favItem} onPress={() => {toggle(recipeid)}}>
                    <FontAwesome name={isFav == true ? 'heart' : 'heart-o'} size={40} color='red' />
                   <Text> {text}</Text>
                </TouchableOpacity>
            </View>
        )
    }
    
    const mapStateToProps = (state) =>({
        favids: state.favids,
    })
    
    const mapDispatchToProps = (dispatch) => ({
        toggle: (recipeid) => dispatch(toggleFavId(recipeid)),
        isFav: (recipeid) => dispatch(isFavourite(recipeid)),
    })
    
    export default connect(mapStateToProps,mapDispatchToProps)(FavIcon)
    
    const styles = StyleSheet.create({
        container: {
          flex: 1,
          flexDirection: 'column',
          backgroundColor: '#fff',
          alignItems: 'flex-start',
          justifyContent: 'center',
        },
        favItem: {
          flexDirection: 'row',
          alignItems: 'center',
          justifyContent: 'flex-start',
          marginTop:10,
          paddingTop:15,
          paddingBottom:15,
          marginLeft:30,
          marginRight:30,
          backgroundColor:'#00BCD4',
          borderRadius:10,
          borderWidth: 1,
          borderColor: '#fff',
          height: 75,
          width: 300,
        }
      });

This if the reducer....the code enters the TOGGLE switch but the state is not updated with the new values.


    import {TOGGLE, IS_FAVOURITE} from '../actions'
    
    export const favids = (state=[], action) => {
        const {type, recipeid} = action
    
        const newRecipe = {
            recipeid: recipeid,
            is_fav: true,
        }
    
        switch (type) {
            case TOGGLE: {
                console.log(`Toggle State = ${JSON.stringify(state)}`)
                console.log(`NEW REcipe ${JSON.stringify(newRecipe)} `)
                // console.log(`Toggle State after adding = ${JSON.stringify(state)}`)
                // return state.map(item=>{ 
                //     state.recipeid === recipeid ? 
                //         {...item, newRecipe} : {...item,newRecipe}
                // })
                return {...state, newRecipe}
            }
            case IS_FAVOURITE: {
                console.log(`Is Favourite state =${JSON.stringify(state)}`)
                return state.map(item=>{ 
                    item.recipeid === recipeid ? 
                        {...item, is_fav: !item.is_fav} : item
                })
            }
            default:
                return state
        }
    }

I've tried different methods of updating the state (see below) but the state is not updated. I've commented out the older code which was not working

            // return state.map(item=>{ 
            //     state.recipeid === recipeid ? 
            //         {...item, newRecipe} : {...item,newRecipe}
            // })
            return {...state, newRecipe}

Any help would be appreciated.

This is the index.js file from the '../actions' folder


    export const TOGGLE = 'TOGGLE'
    export const toggleFavId = id => ({
        type: 'TOGGLE',
        recipeid: id
    })
    
    export const IS_FAVOURITE = 'IS_FAVOURITE'
    export const isFavourite = id => (
        {
            type: 'IS_FAVOURITE',
            recipeid: id
        }
    )
    
    export const TOGGLE_FAV = 'TOGGLE_FAV'
    export const toggleFav = id => ({
        type: 'TOGGLE_FAV',
        recipeid: id,
    })

this is the VisibleFavicon.js file


    import {connect} from 'react-redux'
    import Favicon from '../components/favicon'
    
    const mapStateToProps = state =>({
        favids: state
    })
    
    const mapDispatchToProps = dispatch => ({
        toggleFavIds: id => dispatch ({
            type: 'TOGGLE',
            id 
        }),
    isFavourite : id => dispatch ({
        type: 'IS_FAVOURITE',
        id
    }),
    })
    
    export default connect(mapStateToProps, mapDispatchToProps)(Favicon)

Try to get whole state of redux instead of state.favids and wherever you want to use that state you can access it like props.state.favids:

 const mapStateToProps = (state) =>({
 favids: state,
 })

Heres the solution to the issue, this is the code for the reducer.

import { TOGGLE, IS_FAVOURITE } from '../actions'

export const favids = (state = [], action) => {
    const { type, recipeid } = action

    const newRecipe = {
        recipeid,
        is_fav: true,
    }

    switch (type) {
        case TOGGLE: {
             return state.findIndex(recipe => recipe.recipeid === recipeid) === -1 ?
                [...state, newRecipe] :
                state.map(recipe =>
                    recipe.recipeid === recipeid ?
                        { ...recipe, is_fav: !recipe.is_fav } : recipe
                )
        }
       default:
            return state
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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