存储未在 redux 中更新?

问题描述:

在收藏列表"reducer中

In the "Favorite List" reducer

我有两个辅助函数从数组中添加/删除"项

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

添加运行良好,但删除它并没有在实际时间更新商店,因为我的用户界面中有一个检查器,可以检查数组中是否有这个 song_id 并基于它我更新了心形图标但它确实如此当我调度删除操作时效果不佳,换句话说不重新渲染组件"!

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"!.

动作文件

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,
  };
};

减速器

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;

音乐播放器组件"

 ....
 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);

感谢您的现场演示,它帮助您全面了解情况.问题在于您的视图实际上根本没有使用 Redux 存储中的值.减速器很好,一切都在幕后工作,但请看...

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,
  };
};

这是您的 mapStateToProps 方法,并且 favorite 包含一个收藏曲目数组,每当您分派动作时,这些曲目都会成功更新.你的视图没有相应更新的原因是你没有在任何地方使用这个数组.

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'}
/>

在这段代码中,您要检查的是组件内部状态中 isFavorite 属性的值.添加收藏夹时它起作用的原因是因为您在 addToFavorite 的开头调用了 setState.相反,deleteFromFavorite 缺少 setState 调用,这就是您的图标没有改变的原因.

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.

如果您想使用 Redux 商店中的内容来确定要显示的图标,您应该更改您的代码,使其使用 this.props.favorite,这是实际引用商店并根据您的操作更改的属性.

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'}
  />
}

通过进行此更改,您的组件将真正监听 store 的内容,并且应该在收藏夹数组更改时更新视图.

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.