Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
488 views
in Technique[技术] by (71.8m points)

javascript - Store not updated in redux?

In the "Favorite List" reducer

I have two helper function "Add/Remove" item from the array

the Add work well but Remove it does not update the store in the actual time, because I have a checker in my UI that checks if this song_id in the array or not and bassed on it I update the heart icon BUT it does not work well when I dispatch the remove Action, In Other Words "Not Re-render the component"!.

Action File

import {ADD_TO_FAVORITE, REMOVE_FROM_FAVORITE} from './types';

export const addToFavoriteFunction = track_id => {
  return {
    type: ADD_TO_FAVORITE,
    payload: track_id,
  };
};

export const removeFromFavoriteFunction = track_id => {
  return {
    type: REMOVE_FROM_FAVORITE,
    payload: track_id,
  };
};

Reducer

import {ADD_TO_FAVORITE, REMOVE_FROM_FAVORITE} from '../actions/types';

let initialState = [];

const addSongFav = (songs, songId, flag) => {
  if (songs.some(song => song.track_id === songId)) {
    return songs;
  } else {
    let isFav = {track_id: songId, isFavorite: flag};
    return [...songs, isFav];
  }
};

const removeSongFav = (songs, songId) => {
  const newState = songs.filter(song => song.track_id !== songId);
  return newState;
};


const isFavoriteReducer = (state = initialState, action) => {
  const {payload, type} = action;
  switch (type) {
    case ADD_TO_FAVORITE: {
      return addSongFav(state, payload, true);
    }
    case REMOVE_FROM_FAVORITE:
      return removeSongFav(state, payload);
    default:
      return state;
  }
};

export default isFavoriteReducer;

"Music Player Component"

 ....
 checkFavorite = () => {
    let {currentTrackIndex, tunes} = this.state;
    console.log(tunes[currentTrackIndex].id);
    let id = tunes[currentTrackIndex].id;
    let songs = this.props.favorite;
    let isFavorite = songs.some(song => song.track_id === id);
    this.setState({isFavorite});
  };

componentDidMount() {
    this.checkFavorite();
  }



  addToFavorite = async () => {
    const {tunes, token, currentTrackIndex} = this.state;
    this.setState({isFavorite: true});
    let id = tunes[currentTrackIndex].id;
    try {
      this.props.addToFavoriteAction(id);
      let AuthStr = `Bearer ${token}`;
      const headers = {
        'Content-Type': 'application/json',
        Authorization: AuthStr,
      };
      //  here i send a hit the endoint
    } catch (err) {
      this.setState({isFavorite: false});
      console.log(err);
    }
  };


deleteFromFavorite = async () => {
    const {tunes, token, isFavorite, currentTrackIndex} = this.state;
    let id = tunes[currentTrackIndex].id;
    this.props.removerFromFavoriteAction(id);
    try {
      let AuthStr = `Bearer ${token}`;
      const headers = {
        'Content-Type': 'application/json',
        Authorization: AuthStr,
      };
      // here i send a hit the endoint
    } catch (err) {
      console.log(err);
    }
  };



<Button onPress={() => this.state.isFavorite
                  ? this.deleteFromFavorite()
                  : this.addToFavorite()} >
  <Icon name={this.state.isFavorite ? 'favorite' : 'favorite-border'} />
</Button>

....

const mapDispatchToProps = dispatch => {
  return {
    incrementCount: count => {
      dispatch(incrementCount(count));
    },

    addToFavoriteAction: track_id => {
      dispatch(addToFavoriteFunction(track_id));
    },

    removerFromFavoriteAction: track_id => {
      dispatch(removeFromFavoriteFunction(track_id));
    },
  };
};

mapStateToProps = state => {
  return {
    favorite: state.favorite,
  };
};
export default connect(mapStateToProps, mapDispatchToProps)(MusicPlayer);
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Thanks for the live demo, it helped a lot to see the whole picture. The issue is that your view is not actually using the values in your Redux store at all. The reducer is fine and everything is working behind the scenes, but take a look...

const mapStateToProps = state => {
  return {
    favorite: state,
  };
};

This is your mapStateToProps method, and favorite contains an array of the favorite tracks that is successfully being updated whenever you dispatch an action. The reason why your view is not updated accordingly is that you're not using this array anywhere.

<Icon
  style={{color:"#00f"}}
  type="MaterialIcons"
  name={this.state.isFavorite ? 'favorite' : 'favorite-border'}
/>

In this piece of code, what you're checking is the value of a isFavorite property inside of your component's inner state. The reason why it works when you add a favorite is because you're calling setState at the beginning of addToFavorite. On the contrary, deleteFromFavorite is missing that setState call, which is the reason your icon is not changing.

If you want to use what you have in the Redux store to determine which icon to show, you should change your code so it uses this.props.favorite, which is the property that actually references the store and changes according to your actions.

const isCurrentTrackFavorite = () => {
  const { tunes, currentTrackIndex } = this.state;
  const currentTrackId = tunes[currentTrackIndex].track_id;

  // Check array in the Redux store to see if the track has been added to favorites
  return this.props.favorite.findIndex(track => track.track_id === currentTrackId) != -1;
};

render() {
  <Icon
    style={{color:"#00f"}}
    type="MaterialIcons"
    name={isCurrentTrackFavorite() ? 'favorite' : 'favorite-border'}
  />
}

By making this change, your component will be really listening to the contents of the store and should update the view whenever the array of favorites changes.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...