反应 redux 不可变状态
react redux immutable state
我创建了一个喜欢按钮和一个不喜欢按钮。默认情况下,我的图片有不喜欢按钮。当我点击不喜欢按钮时,我希望这个按钮消失,而喜欢按钮取而代之。我的问题是状态在我检查时发生了变化,但我在页面上看不到变化,除非我重新加载页面:变化保存在数据库中。有谁知道如何解决这个问题?
这是我的减速器。
我的初始状态:
const initialState = {
loading: false,
stories: [],
error: "",
currentPage: 1,
totalPages: null,
totalStories: null
}
case LIKE:
return {
...state,
stories: state.stories.map(storie => {
if(storie.id === action.payload.id) {
return { ...storie,
userlikes: action.payload.userlikes
}
} else {
return storie;
}
})
}
这是我所有的reducer
import {FETCH_GALLERY_REQUEST, FETCH_GALLERY_SUCCESS, FETCH_GALLERY_FAILURE, GALLERY_CLEAR, LIKE, DISLIKE } from "./galleryTypes";
const initialState = {
loading: false,
stories: [],
error: "",
currentPage: 1,
totalPages: null,
totalStories: null
}
const galleryReducer = (state = initialState, action) => {
switch(action.type) {
case FETCH_GALLERY_REQUEST:
return {
...state,
loading: action.payload,
}
case GALLERY_CLEAR:
return {
...state,
loading: false,
stories: [],
error: "",
currentPage: 1,
totalPages: null,
totalStories: null
}
case FETCH_GALLERY_SUCCESS:
return {
...state,
loading: false,
stories: [...state.stories, ...action.payload].filter(
(storie, index) => index === [...state.stories, ...action.payload].findIndex(
elem => elem.id === storie.id && elem.id === storie.id
)
),
currentPage: action.currentPage,
totalPages: action.totalPages,
totalStories: action.totalStories,
error: ""
}
case FETCH_GALLERY_FAILURE:
return {
...state,
loading: false,
stories: [],
error: action.payload
}
case LIKE:
return {
...state,
stories: state.stories.map(storie => {
if(storie.id === action.payload.id) {
return {
...storie,
userlikes: action.payload.userlikes
}
} else {
return storie;
}
})
}
default:
return state;
}
}
export default galleryReducer
这是我的 vue 组件
// permet d'ajouter un like
addLike = (story_id, user_id, index) => {
const data = {
story_id: story_id,
user_id: user_id
}
this.props.like(story_id);
this.props.fetchLike(data);
}
// permet denlever un like
removeLike = (story_id, user_id) => {
this.setState({
story_id: story_id
})
const data = {
story_id: story_id,
user_id: user_id
}
this.props.disLike(story_id);
this.props.fetchDislike(story_id, user_id);
}
我的渲染
{storiesData.stories.map((storie, index) => (
<div
key={index}
className="everyprofile-container_details item"
style={{ height: "450px" }}
>
<div className="everyprofile_name">
<span className="everyProfile-firstname"> {storie.firstname} </span>
<span className="everyProfile-lastname"> {storie.lastname} </span>
</div>
<div className="everyprofile-photo_cadre">
<div
className="everyprofile-photo"
style={{
backgroundImage: `url(${config.API_URL}resources/pictures_min/${storie.picture_path})`,
backgroundPositionY: `${storie.bg_position_y}%`,
backgroundPositionX: `${storie.bg_position_x}%`,
backgroundSize: "cover"
}}
>
{storie.userlikes == 1 ? (
<button
onClick={() => this.removeLike(storie.id, user_id, index)}
className="everyprofile-like-btn"
style={{ color: "#FF0000" }}
>
<Icon size={40} icon={ic_favorite} />
</button>
) : (
<button
onClick={() => this.addLike(storie.id, user_id, index)}
className="everyprofile-like-btn"
style={{ color: "#FF0000" }}
>
<Icon size={40} icon={ic_favorite_border} />
</button>
)}
</div>
</div>
<div className="everyprofile-container-story">
<div className="everyprofile-story">{storie.story}</div>
</div>
</div>
))}
const mapStateToProps = (state) => {
return {
storiesData: state.stories,
loading: state.stories.loading,
currentPage: state.stories.currentPage,
totalPages: state.stories.totalPages,
totalStories: state.stories.totalStories,
validateStory: state.validateStorie.validateStory,
searchStatus: state.searchStatus.searchBar,
query: state.query.query
}
}
const mapDispatchToProps = (dispatch) => {
return {
// fetchEveryProfile: (storyId, userId) => dispatch(fetchEveryProfile(storyId, userId)),
fetchLike: (data) => dispatch(fetchLike(data)),
fetchDislike: (story_id, user_id) => dispatch(fetchDislike(story_id, user_id)),
like: (story_id) => dispatch(like(story_id)),
disLike: (story_id) => dispatch(disLike(story_id)),
fetchGalleryFirst: (searchInfo) => dispatch(fetchGalleryFirst(searchInfo)),
fetchGallery: (searchInfo) => dispatch(fetchGallery(searchInfo))
}
}
export default connect(mapStateToProps, mapDispatchToProps)(EvryProfile)
这是动作
// Permet d'enlever le bouton like
export const like = (story_id) => {
return {
type: LIKE,
payload: {
id: story_id,
userlikes: 1
}
}
}
// Permet d'enlever le bouton dislike
export const disLike = (id) => {
return {
type: DISLIKE,
payload: id
}
}
问题
您的减速器似乎缺少案例处理 DISLIKE
。根据您的 LIKE
案例和 UI 逻辑,我假设将 stories[someIndex].userlikes
更新为 1
以外的任何值应该将不喜欢按钮切换回喜欢按钮。
追踪步骤
- 单击按钮并调用
removeLike
removeLike
调度 disLike
和 fetchDislike
动作
- 我假设
fetchDislike
是一个异步操作,即 thunk、epic、saga 等...并且有效,但是 dislike
应该在 reducer 中处理。
- 查看 reducer,看不到 case 处理
DISLIKE
解决方案
添加案例以处理 DISLIKE
并更新特定故事的 userlikes
属性.
switch (true) {
case DISLIKE:
return {
...state,
stories: state.stories.map((story) =>
storie.id === action.payload.id
? {
...story,
userlikes: 0
}
: story
)
};
}
我创建了一个喜欢按钮和一个不喜欢按钮。默认情况下,我的图片有不喜欢按钮。当我点击不喜欢按钮时,我希望这个按钮消失,而喜欢按钮取而代之。我的问题是状态在我检查时发生了变化,但我在页面上看不到变化,除非我重新加载页面:变化保存在数据库中。有谁知道如何解决这个问题? 这是我的减速器。
我的初始状态:
const initialState = {
loading: false,
stories: [],
error: "",
currentPage: 1,
totalPages: null,
totalStories: null
}
case LIKE:
return {
...state,
stories: state.stories.map(storie => {
if(storie.id === action.payload.id) {
return { ...storie,
userlikes: action.payload.userlikes
}
} else {
return storie;
}
})
}
这是我所有的reducer
import {FETCH_GALLERY_REQUEST, FETCH_GALLERY_SUCCESS, FETCH_GALLERY_FAILURE, GALLERY_CLEAR, LIKE, DISLIKE } from "./galleryTypes";
const initialState = {
loading: false,
stories: [],
error: "",
currentPage: 1,
totalPages: null,
totalStories: null
}
const galleryReducer = (state = initialState, action) => {
switch(action.type) {
case FETCH_GALLERY_REQUEST:
return {
...state,
loading: action.payload,
}
case GALLERY_CLEAR:
return {
...state,
loading: false,
stories: [],
error: "",
currentPage: 1,
totalPages: null,
totalStories: null
}
case FETCH_GALLERY_SUCCESS:
return {
...state,
loading: false,
stories: [...state.stories, ...action.payload].filter(
(storie, index) => index === [...state.stories, ...action.payload].findIndex(
elem => elem.id === storie.id && elem.id === storie.id
)
),
currentPage: action.currentPage,
totalPages: action.totalPages,
totalStories: action.totalStories,
error: ""
}
case FETCH_GALLERY_FAILURE:
return {
...state,
loading: false,
stories: [],
error: action.payload
}
case LIKE:
return {
...state,
stories: state.stories.map(storie => {
if(storie.id === action.payload.id) {
return {
...storie,
userlikes: action.payload.userlikes
}
} else {
return storie;
}
})
}
default:
return state;
}
}
export default galleryReducer
这是我的 vue 组件
// permet d'ajouter un like
addLike = (story_id, user_id, index) => {
const data = {
story_id: story_id,
user_id: user_id
}
this.props.like(story_id);
this.props.fetchLike(data);
}
// permet denlever un like
removeLike = (story_id, user_id) => {
this.setState({
story_id: story_id
})
const data = {
story_id: story_id,
user_id: user_id
}
this.props.disLike(story_id);
this.props.fetchDislike(story_id, user_id);
}
我的渲染
{storiesData.stories.map((storie, index) => (
<div
key={index}
className="everyprofile-container_details item"
style={{ height: "450px" }}
>
<div className="everyprofile_name">
<span className="everyProfile-firstname"> {storie.firstname} </span>
<span className="everyProfile-lastname"> {storie.lastname} </span>
</div>
<div className="everyprofile-photo_cadre">
<div
className="everyprofile-photo"
style={{
backgroundImage: `url(${config.API_URL}resources/pictures_min/${storie.picture_path})`,
backgroundPositionY: `${storie.bg_position_y}%`,
backgroundPositionX: `${storie.bg_position_x}%`,
backgroundSize: "cover"
}}
>
{storie.userlikes == 1 ? (
<button
onClick={() => this.removeLike(storie.id, user_id, index)}
className="everyprofile-like-btn"
style={{ color: "#FF0000" }}
>
<Icon size={40} icon={ic_favorite} />
</button>
) : (
<button
onClick={() => this.addLike(storie.id, user_id, index)}
className="everyprofile-like-btn"
style={{ color: "#FF0000" }}
>
<Icon size={40} icon={ic_favorite_border} />
</button>
)}
</div>
</div>
<div className="everyprofile-container-story">
<div className="everyprofile-story">{storie.story}</div>
</div>
</div>
))}
const mapStateToProps = (state) => {
return {
storiesData: state.stories,
loading: state.stories.loading,
currentPage: state.stories.currentPage,
totalPages: state.stories.totalPages,
totalStories: state.stories.totalStories,
validateStory: state.validateStorie.validateStory,
searchStatus: state.searchStatus.searchBar,
query: state.query.query
}
}
const mapDispatchToProps = (dispatch) => {
return {
// fetchEveryProfile: (storyId, userId) => dispatch(fetchEveryProfile(storyId, userId)),
fetchLike: (data) => dispatch(fetchLike(data)),
fetchDislike: (story_id, user_id) => dispatch(fetchDislike(story_id, user_id)),
like: (story_id) => dispatch(like(story_id)),
disLike: (story_id) => dispatch(disLike(story_id)),
fetchGalleryFirst: (searchInfo) => dispatch(fetchGalleryFirst(searchInfo)),
fetchGallery: (searchInfo) => dispatch(fetchGallery(searchInfo))
}
}
export default connect(mapStateToProps, mapDispatchToProps)(EvryProfile)
这是动作
// Permet d'enlever le bouton like
export const like = (story_id) => {
return {
type: LIKE,
payload: {
id: story_id,
userlikes: 1
}
}
}
// Permet d'enlever le bouton dislike
export const disLike = (id) => {
return {
type: DISLIKE,
payload: id
}
}
问题
您的减速器似乎缺少案例处理 DISLIKE
。根据您的 LIKE
案例和 UI 逻辑,我假设将 stories[someIndex].userlikes
更新为 1
以外的任何值应该将不喜欢按钮切换回喜欢按钮。
追踪步骤
- 单击按钮并调用
removeLike
removeLike
调度disLike
和fetchDislike
动作- 我假设
fetchDislike
是一个异步操作,即 thunk、epic、saga 等...并且有效,但是dislike
应该在 reducer 中处理。 - 查看 reducer,看不到 case 处理
DISLIKE
解决方案
添加案例以处理 DISLIKE
并更新特定故事的 userlikes
属性.
switch (true) {
case DISLIKE:
return {
...state,
stories: state.stories.map((story) =>
storie.id === action.payload.id
? {
...story,
userlikes: 0
}
: story
)
};
}