我有一个播放列表组件,其中包含歌曲列表。 OnComponentDidMount可以从axios获取数据,并使用GET_PLAYLIST操作将其填充到商店中的列表中。
有一个“添加到播放列表”按钮,该按钮调用UPDATE_PLAYLIST操作,该操作应将选定的歌曲添加到商店中的播放列表列表中,然后通过axios post调用将新歌曲添加到firebase数据库中。
状态更改时,播放列表组件应该更新,但我不知道为什么不是这样?
我的Playlist.js组件:
import React, { Component } from "react";
import { connect } from "react-redux";
import Auxilliary from "../../hoc/Auxilliary";
import PlayListItem from "../../components/PlayListItem/PlayListItem";
import classes from "./Playlist.css";
import * as actionTypes from "../../store/actions";
import axios from "../../hoc/axios-Firebase";
class Playlist extends Component {
componentDidMount() {
const searchQuery = "/playlist.json";
axios
.get(searchQuery)
.then(response => {
const playlistSongs = [];
for (let song in response.data) {
playlistSongs.push({
artistName: response.data[song].artistName,
trackName: response.data[song].track,
collectionName: response.data[song].collectionName
});
}
this.props.onGetPlaylist(playlistSongs);
})
.catch(error => {
console.log(error);
});
}
render() {
if (this.props.playlist.length > 0) {
const results = this.props.playlist.map((playlistItem, index) => {
return (
<PlayListItem
key={index}
artist={playlistItem.artistName}
track={playlistItem.trackName}
album={playlistItem.collectionName}
/>
);
});
return (
<Auxilliary>
<table className={classes.playlistTable}>
<thead>
<tr>
<th>Track</th>
<th>Album</th>
<th>Artist</th>
</tr>
</thead>
<tbody>{results}</tbody>
</table>
</Auxilliary>
);
} else {
return null;
}
}
}
const mapStateToProps = state => {
return {
playlist: state.playlist
};
};
const mapDispatchToProps = dispatch => {
return {
onGetPlaylist: value =>
dispatch({
type: actionTypes.GET_PLAYLIST,
playlist: value
})
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(Playlist);
带有“添加到播放列表”按钮的组件:
import React, { Component } from "react";
import { connect } from "react-redux";
import Auxilliary from "../../hoc/Auxilliary";
import * as actionTypes from "../../store/actions";
import axios from "../../hoc/axios-Firebase";
import classes from "./SongInfo.css";
class SongInfo extends Component {
constructor(props) {
super(props);
this.addToPlaylistHandler = this.addToPlaylistHandler.bind(this);
}
addToPlaylistHandler(
track,
trackID,
artistName,
collectionName,
kind,
trackPrice
) {
const data = {
track: track,
trackID: trackID,
artistName: artistName,
collectionName: collectionName,
kind: kind,
trackPrice: trackPrice
};
this.props.onUpdatePlaylist(data);
axios
.post("/playlist.json", data)
.then(response => {
console.log(response);
})
.catch(error => {
console.log(error);
});
}
render() {
return (
<Auxilliary>
<table>
<thead>
<tr>
<th>Track</th>
<th>Track ID</th>
<th>Artist Name</th>
<th>Collection Name</th>
<th>Kind</th>
<th>Track Price</th>
</tr>
</thead>
<tbody>
<tr>
<td>{this.props.track}</td>
<td>{this.props.id}</td>
<td>{this.props.artistName}</td>
<td>{this.props.collectionName}</td>
<td>{this.props.kind}</td>
<td>{this.props.trackPrice}</td>
</tr>
</tbody>
</table>
<button
className={classes.addToPlaylist}
onClick={this.addToPlaylistHandler(
this.props.track,
this.props.id,
this.props.artistName,
this.props.collectionName,
this.props.kind,
this.props.trackPrice
)}
>
Add to Playlist
</button>
</Auxilliary>
);
}
}
const mapStateToProps = state => {
return {
playlist: state.playlist
};
};
const mapDispatchToProps = dispatch => {
return {
onUpdatePlaylist: value =>
dispatch({
type: actionTypes.UPDATE_PLAYLIST,
playlistItem: value
})
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(SongInfo);
我的减速器:
import * as actionTypes from "./actions";
const initialState = {
searchValue: "",
finalSearchValue: "",
searchResults: [],
sliceStart: 0,
sliceEnd: 25,
nextDisabled: false,
prevDisabled: true,
searchResult: {
id: null,
artistId: null,
artistName: "",
track: "",
collectionName: "",
kind: "",
trackPrice: null
},
playlist: []
};
const reducer = (state = initialState, action) => {
switch (action.type) {
case actionTypes.UPDATE_INPUT_VALUE:
return {
...state,
searchValue: action.searchValue
};
case actionTypes.SUBMIT_QUERY:
return {
...state,
finalSearchValue: action.finalSearchValue
};
case actionTypes.SET_SEARCH_RESULTS:
return {
...state,
searchResults: action.searchResults
};
case actionTypes.GET_PLAYLIST:
return {
...state,
playlist: action.playlist
};
case actionTypes.UPDATE_PLAYLIST:
const newPlaylist = state.playlist;
newPlaylist.push(action.playlistItem);
return {
...state,
playlist: newPlaylist
};
case actionTypes.SET_INFO_SEARCH_RESULT:
return {
...state,
searchResult: {
id: action.searchResult.id,
artistId: action.searchResult.artistId,
artistName: action.searchResult.artistName,
track: action.searchResult.track,
collectionName: action.searchResult.collectionName,
kind: action.searchResult.kind,
trackPrice: action.searchResult.trackPrice
}
};
case actionTypes.GET_PREV_25:
if (state.sliceStart - 25 >= 0) {
const newSliceStart = state.sliceStart - 25;
const newSliceEnd = state.sliceEnd - 25;
state.sliceStart = newSliceStart;
state.sliceEnd = newSliceEnd;
state.nextDisabled = false;
if (0 <= newSliceStart) {
state.prevDisabled = true;
}
}
return {
...state,
sliceStart: state.sliceStart,
sliceEnd: state.sliceEnd,
prevDisabled: state.prevDisabled,
nextDisabled: state.nextDisabled
};
case actionTypes.GET_NEXT_25:
if (state.sliceEnd < state.searchResults.length) {
const newSliceStart = state.sliceStart + 25;
const newSliceEnd = state.sliceEnd + 25;
state.sliceStart = newSliceStart;
state.sliceEnd = newSliceEnd;
state.prevDisabled = false;
if (state.searchResults.length === newSliceEnd) {
state.nextDisabled = true;
}
}
return {
...state,
sliceStart: state.sliceStart,
sliceEnd: state.sliceEnd,
prevDisabled: state.prevDisabled,
nextDisabled: state.nextDisabled
};
default:
return state;
}
};
export default reducer;
答案 0 :(得分:3)
一个问题可能是您正在直接修改状态,请尝试以下操作:
case actionTypes.UPDATE_PLAYLIST:
return {
...state,
playlist: [...state.playlist, action.playlistItem]
};
此外,您没有正确调用该动作,还需要将其包装到一个函数中:
<button
className={classes.addToPlaylist}
onClick={() => this.addToPlaylistHandler( // onClick expects a function and not its result
this.props.track,
this.props.id,
this.props.artistName,
this.props.collectionName,
this.props.kind,
this.props.trackPrice
)}
>
顺便说一句,您真的不需要在这里将所有这些道具作为参数传递,更容易在addToPlaylistHandler
内部访问它们。
答案 1 :(得分:0)
您在按钮上的onClick
处理函数应该具有对处理函数的引用,但是当前您正在调用它,并且onClick
具有该方法返回的值(在这种情况下,{{1} }返回addToPlaylistHandler
)
要解决此问题,您需要将onClick更改为一个内联函数,或者将您的处理程序包装到另一个返回函数中,从而携带数据。
方法1:使onClick成为嵌入式函数
undefined
方法2:重写您的addToPlaylistHandler以在其中携带参数
<button
className={classes.addToPlaylist}
onClick={() => this.addToPlaylistHandler(
this.props.track,
this.props.id,
this.props.artistName,
this.props.collectionName,
this.props.kind,
this.props.trackPrice
)}
>
Add to Playlist
</button>
如果您的开发环境支持类属性语法,则可以缩短处理程序代码(无需在构造函数中绑定处理程序:
addToPlaylistHandler(
track,
trackID,
artistName,
collectionName,
kind,
trackPrice
) {
return () => {
// this one will be executed on click
const data = {
track: track,
trackID: trackID,
artistName: artistName,
collectionName: collectionName,
kind: kind,
trackPrice: trackPrice
};
axios
.post("/playlist.json", data)
.then(response => {
// Ideally, you should update the state on sucessful post
this.props.onUpdatePlaylist(data);
console.log(response);
})
.catch(error => {
// and handle the error properly
console.log(error);
});
}
}