where can i dispatch the action - redux?

安稳与你 提交于 2020-03-25 19:19:29

问题


I'm working on a music app, and I have a Purchase quota, that allows users to use the app.

So if a user plays 20 track music I will appear to him a modal or something.

So I have a component that's for play music "controller" name as <MusicPlayer/>,

I add it in every screen I have music tracks there when user press to any track card I navigate them to screen that contains

so i want to do some counter when user playing a music increase it +1

so i don't know where can I make this dispatch, in MusicPlayer components?

or in every screen that contained this component and pass it as props?

code

actions/countPlayAction.js

import {SET_COUNT} from './types';

export const setCount = count => {
  return {
    type: SET_COUNT,
    payload: count,
  };
};

reducer/countPlayReducer.js

import {SET_COUNT} from '../actions/types';

let initial_state = {
  count: 0,
};
const countPlayReducer = (state = initial_state, action) => {
  switch (action.type) {
    case SET_COUNT:
      state = {
        ...state,
        count: state.count + action.payload,
      };
      break;
  }
  return state;
};

export default countPlayReducer;

musicPlayer component

class MusicPlayer extends Component {
  constructor(props) {
    super(props);
    this.state = {
      tunes: props.tunes,
      currentTrackIndex: props.currentTrackIndex,
      rate: 1,
      duration: 1,
      currentTime: 0,
      paused: true,
      loading: true,
    };
  }

  onLoad = data => {
    this.setState({
      duration: Math.floor(data.duration),
      loading: false,
      paused: true,
    });
  };

  render() {
    return (
      <View>
        <View>
          <Video
            ref={ref => {
              this.player = ref;
            }}
            source={{
              uri: this.state.tunes[this.state.currentTrackIndex].url,
            }}
            paused={this.state.paused}
            playInBackground={true}
            playWhenInactive={true}
            onLoad={this.onLoad}
            onProgress={this.onProgress.bind(this)}
            onEnd={this.onEnd}
            controls={false}
          />
          <View style={styles.time}>
            <View style={styles.timeChildView}>
              <Text style={styles.timeChildViewText}>
                {this.minutesAndSeconds(this.state.currentTime)}
              </Text>
            </View>
            <View style={styles.timeChildView}>
              <Text style={styles.timeChildViewText}>
                {this.minutesAndSeconds(this.state.duration)}
              </Text>
            </View>
          </View>

          <View style={styles.slider}>
            {/* For circle play  */}
            <Slider
              thumbTintColor="#ff4865"
              maximumTrackTintColor="grey"
              minimumTrackTintColor="#ff4865"
              style={styles.seekBar}
              step={1}
              minimumValue={0}
              maximumValue={this.state.duration}
              value={this.state.currentTime}
              onValueChange={this.changeValue}
              onSlidingComplete={this.onSlidingComplete}
            />
          </View>

          <View style={styles.controls}>

            {this.state.loading ? (
              <ActivityIndicator size="large" color="#ff4865" />
            ) : (
              <View style={styles.flexRow}>
                <View>
                  {!this.state.paused ? (
                    <Button
                      transparent
                      style={styles.btnSection}
                      color="white"
                      onPress={() =>
                        this.setState({paused: !this.state.paused})
                      }>
                      <Icon name="md-pause" style={styles.iconColor} />
                    </Button>
                  ) : (
                    <Button
                      transparent
                      style={styles.btnSection}
                      color="white"
                      onPress={() =>
                        this.setState({paused: !this.state.paused})
                      }>
                      <Icon name="md-play" style={styles.iconColor} />
                    </Button>
                  )}
                </View>
              </View>
            )}
          </View>
        </View>
      </View>
    );
  }
}

export default MusicPlayer;

What I made, it's increase count +1 in every time i play a track, but i don't know if that's a right way or not

in music player component

 onLoad = data => {
    this.setState({
      duration: Math.floor(data.duration),
      loading: false,
      paused: true,
    });
    this.props.setCount(1)
    reactotron.log(store.getState());
  };

const mapDispatchToProps = dispatch => {
  return {
    setCount: count => {
      dispatch(setCount(count));
    },
  };
};
// export default MusicPlayer;
export default connect(null, mapDispatchToProps)(MusicPlayer);

回答1:


It looks logically done, although have a feeling of overhead introduced by redux (that's usual on small scale apps). I would also advice to change setCount to incrementCount, so that you don't need to have an absolute value in the component which increases the value.

You followed the Component-Container principle, what is not bad, but in your case you don't get any data from mapStateToProps and it forced you to have some boilerplate code inside of mapDispatchToProps.

An idea how to simplify it - you can wrap your component with connect and then you'll have dispatch available under props object inside of your component, so that you can immediately dispatch the action from onLoad. It will look like this:

onLoad = data => {
    this.props.dispatch(setCount(1));
};

Final couple of words, if you don't have any other use cases for redux have a look at React.Context as you'll have less boilerplate with it :)



来源:https://stackoverflow.com/questions/60130935/where-can-i-dispatch-the-action-redux

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!