问题
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