Как правильно прописать extraReducer в постах, который следит за добавлением или удалением лайка
Есть такой массив постов, пытаюсь прописать экстраредюсер, следящий за лайками, но никак не получается сделать это правильно. Всё, чего смог достичь это либо при лайке перезагружается весь компонент с постами, либо (текущий вариант) при лайке визуально увеличивается количество лайков на всех постах, работает 2 клика подряд потом ничего не меняет.
На беке на данный момент одна функция, которая проверяет,существует ли лайк или нет, и создаёт его или удаляет в зависимости от проверки. Лайки связаны с постами и юзерами через связь в секвалайзе belongsToMany
https://i.sstatic.net/rln66.png
likeslice
const initialState = {
likes: []
}
export const upvotePost = createAsyncThunk(
'likes/upvotePost',
async (id, { rejectWithValue, dispatch }) => {
try {
const response = await axios.post(`/posts/${id}/likes`);
dispatch(addLike(response.data.like))
} catch (error) {
rejectWithValue(error.message);
}
}
)
// export const unlikePost = createAsyncThunk(
// 'likes/unlikePost',
// async (id, { rejectWithValue, dispatch }) => {
// try {
// await axios.delete(`/posts/${id}/likes`);
// dispatch(unlike(id))
// } catch (error) {
// rejectWithValue(error.message);
// }
// }
// )
export const getPostLikes = createAsyncThunk(
'likes/getPostLikes',
async(id, {rejectWithValue, dispatch}) => {
try {
const response = await axios(`/posts/${id}/likes`);
dispatch(getLikes(response.data.postLikes));
} catch (error) {
rejectWithValue(error.message);
}
}
)
export const likeSlice = createSlice({
name: 'likes',
initialState,
reducers: {
addLike: (state, action) => {
state.likes.push(action.payload);
},
// unlike: (state, action) => {
// state.likes = state.likes.filter(el => el.id !== action.payload)
// },
getLikes: (state, action) => {
state.likes = action.payload;
}
}
})
export const { addLike, unlike, getLikes } = likeSlice.actions;
export default likeSlice.reducer;
postSlice
const initialState = {
posts: [],
post_id: {}
}
export const addNewPost = createAsyncThunk(
'posts/addNewPost',
async (value, { rejectWithValue, dispatch }) => {
try {
const response = await axios.post('/posts', value);
dispatch(addPost(response.data.newPost));
} catch (error) {
rejectWithValue(error.message);
}
}
)
export const getAllPosts = createAsyncThunk(
'posts/getAllPosts',
async (_, { rejectWithValue, dispatch }) => {
try {
const response = await axios('/posts');
dispatch(getPosts(response.data.allPosts));
} catch (error) {
rejectWithValue(error.message);
}
}
)
export const removePost = createAsyncThunk(
'posts/removePost',
async (id, { rejectWithValue, dispatch }) => {
try {
await axios.delete(`/posts/${id}`);
dispatch(deletePost(id));
} catch (error) {
rejectWithValue(error.message);
}
}
)
export const getOnePost = createAsyncThunk(
'posts/getOnePost',
async (id, { rejectWithValue, dispatch }) => {
try {
const response = await axios(`/posts/${id}`);
const result = {
...response.data.onePost,
userId: response.data.onePost.User.id,
userName: response.data.onePost.User.name,
userEmail: response.data.onePost.User.email,
userInfo: response.data.onePost.User.info,
userAvatar: response.data.onePost.User.avatar
}
dispatch(getPostById(result));
} catch (error) {
rejectWithValue(error.message);
}
}
)
export const postSlice = createSlice({
name: 'posts',
initialState,
reducers: {
addPost: (state, action) => {
state.posts.push(action.payload);
},
getPosts: (state, action) => {
state.posts = action.payload;
},
deletePost: (state, action) => {
state.posts = state.posts.filter(el => el.id !== action.payload);
},
getPostById: (state, action) => {
state.post_id = action.payload
}
},
extraReducers: (builder) => {
builder.addCase(likeSlice.actions.addLike, (state, action) => {
console.log('extra reducer LIKE payload', action.payload);
state.posts = state.posts.map(post => {
if (post.likedBy.map(user => user.Likes !== action.payload)) {
post.likedBy.push(action.payload)
return {...post }
} else {
return post
}
})
})
// builder.addCase(likeSlice.actions.unlike, (state, action) => {
// console.log('extra reducer UNLIKE', 'payload', action.payload);
// state.post_id = action.payload
// state.posts = state.posts.filter(el => el.id !== action.payload)
// })
},
})
const { addPost, getPosts, deletePost, getPostById } = postSlice.actions;
export default postSlice.reducer;
payload выглядит так
extra reducer LIKE payload
{post_id: 51, user_id: 10, updatedAt: '2023-06-09T12:43:25.871Z', createdAt: '2023-06-09T12:43:25.871Z'}