reactjs - 使 React 组件在商店中更改状态时重新渲染
问题描述
我有一个包含歌曲列表的播放列表组件。OnComponentDidMount 它从 axios 获取数据并使用操作 GET_PLAYLIST 将其填充到存储中的列表中。
有一个“添加到播放列表”按钮调用 UPDATE_PLAYLIST 操作,该操作应将选定的歌曲添加到存储中的播放列表列表,然后 axios 发布调用将新歌曲添加到 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;
解决方案
一个问题可能是您正在直接修改状态,请尝试以下操作:
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
。
推荐阅读
- javascript - 在括号上的 JavaScript 中遇到问题
- java - 使用spring客户端删除RabbitMQ中的所有队列
- c# - Map MouseLeftButtonUp 并不总是触发
- html - 如何将按钮对齐到屏幕html的中心
- reactjs - 无服务器 lambda 函数无法与 CORS 反应
- flutter - 参数类型“Widget”不能分配给参数类型“PreferredSizeWidget?”。颤振中appBar发生错误
- angular - 在 Angular 中,如何在材质对话框模板中使用自定义验证器
- php - 如何从数组中隐藏数组索引号
- python - 删除 RGB 值为黑色 (0,0,0) 的 pandas 数据帧中的行
- node.js - Mongoose 不更新文档