UseReducer Hook dispatch twice-ReactJS
UseReduce Hook dispatch twice-ReactJS
我开发了一个小应用,目的是研究react hooks。该应用程序包括在一个部分中写下艺术家的名字。在下一节中,一个类似的表格,用于填写每个艺术家的专辑。
我将所有组件分开,还有上下文、状态和缩减程序。对于每个艺术家、专辑和歌曲,我都有一个单独的上下文。当我点击艺术家按钮时,我想过滤专辑以便只显示他们的专辑。但是两次使用 reducer dispatch 并且在控制台日志中它告诉我两者都来自 reducer 文件。
有意思的是,我第一次点击的时候,只经过了一次,但是第二次我看到我select一个调度员两次
另一件有趣的事情是,当我更改 selected 艺术家时,它会删除状态专辑,这是我拥有所有专辑的地方。它不会过滤它们,而是会删除它们。
这是我单击以调用每个艺术家的 ID 的表单,我将当前 selected 艺术家发送到艺术家上下文和专辑上下文
import React, { useContext } from "react";
import AlbumContext from "../../context/Album/AlbumContext";
import ArtistContext from "../../context/Artist/ArtistContext";
const Artist = ({ item }) => {
const albumContext = useContext(AlbumContext);
const { getArtist } = albumContext;
const artistContext = useContext(ArtistContext);
const { artist, getselectedArtist } = artistContext;
const handleSelect = (artist_id) => {
getArtist(artist_id);
getselectedArtist(artist_id);
};
return (
<>
<div
style={{ border: "1px solid black", margin: "10px", padding: "5px" }}
>
<p>{item.name}</p>
<button type="button">Edit</button>
<button type="button">Delete</button>
<button type="button" onClick={() => handleSelect(item.id)}>
Select
</button>
</div>
</>
);
};
export default Artist;
第二个是 ALBUMSTATE,我在其中调用函数 getArtist 来调度并获取该 selected 艺术家 的所有专辑
import React, { useReducer } from "react";
import AlbumContext from "./AlbumContext";
import AlbumReducer from "./AlbumReducer";
import { GET_ARTIST, ADD_ALBUM, VALIDATE_FORM } from "../../types";
const AlbumState = (props) => {
const initialState = {
albums: [],
errorform: false,
selectedartist: "",
};
const [state, dispatch] = useReducer(AlbumReducer, initialState);
//-----METHODS-----//
const addAlbum = (album) => {
dispatch({
type: ADD_ALBUM,
payload: album,
});
};
const setError = (error) => {
dispatch({
type: VALIDATE_FORM,
payload: error,
});
};
const getArtist = (id) => {
dispatch({
type: GET_ARTIST,
payload: id,
});
};
return (
<AlbumContext.Provider
value={{
selectedartist: state.selectedartist,
albums: state.albums,
errorform: state.errorform,
addAlbum,
setError,
getArtist,
}}
>
{props.children}
</AlbumContext.Provider>
);
};
export default AlbumState;
这是 ALBUMREDUCER
import { GET_ARTIST, ADD_ALBUM, VALIDATE_FORM } from "../../types";
export default (state, action) => {
switch (action.type) {
case ADD_ALBUM:
return {
...state,
albums: [action.payload, ...state.albums],
};
case VALIDATE_FORM:
return {
...state,
errorform: action.payload,
};
case GET_ARTIST:
console.log(action.payload);
return {
...state,
selectedartist: action.payload,
albums: state.albums.filter(
(album) => album.artist_creator === action.payload
),
};
return {
...state,
selectedartist: action.payload,
};
default:
return state;
}
};
这里有两件事你需要考虑
- 您正在使用 React.strictMode,其中 React 在开发期间有意调用分派方法两次。根据反应文档
Strict mode can’t automatically detect side effects for you, but it
can help you spot them by making them a little more deterministic.
This is done by intentionally double-invoking the following functions:
- Class component constructor, render, and shouldComponentUpdate methods
- Class component static getDerivedStateFromProps method
- Function component bodies
- State updater functions (the first argument to setState)
- Functions passed to useState, useMemo, or useReducer
- 其次,您没有附加任何带有艺术家的专辑,因此您的每张专辑的 artist_creator 始终为空,当您尝试基于它进行过滤时,将 return 一个空数组
case GET_ARTIST:
console.log(action.payload, state.albums, "getArtistalbum");
return {
...state,
selectedartist: action.payload,
albums: state.albums.filter(
album => album.artist_creator === action.payload
) // This returns empty array
};
这里最后要注意的是,您正在使用过滤后的 redux 覆盖原始相册数组,因此您的所有相册数据都将被删除。而是为过滤的项目保留一个单独的键并像
一样过滤它
个案GET_ARTIST:
console.log(action.payload, state.albums, "getArtistalbum");
return{
...状态,
选定的艺术家:action.payload,
所选专辑:state.albums.filter(
专辑 => album.artist_creator === action.payload
) // 从所有相册中筛选出的选定相册的不同键
};
我开发了一个小应用,目的是研究react hooks。该应用程序包括在一个部分中写下艺术家的名字。在下一节中,一个类似的表格,用于填写每个艺术家的专辑。
我将所有组件分开,还有上下文、状态和缩减程序。对于每个艺术家、专辑和歌曲,我都有一个单独的上下文。当我点击艺术家按钮时,我想过滤专辑以便只显示他们的专辑。但是两次使用 reducer dispatch 并且在控制台日志中它告诉我两者都来自 reducer 文件。
有意思的是,我第一次点击的时候,只经过了一次,但是第二次我看到我select一个调度员两次
另一件有趣的事情是,当我更改 selected 艺术家时,它会删除状态专辑,这是我拥有所有专辑的地方。它不会过滤它们,而是会删除它们。
这是我单击以调用每个艺术家的 ID 的表单,我将当前 selected 艺术家发送到艺术家上下文和专辑上下文
import React, { useContext } from "react";
import AlbumContext from "../../context/Album/AlbumContext";
import ArtistContext from "../../context/Artist/ArtistContext";
const Artist = ({ item }) => {
const albumContext = useContext(AlbumContext);
const { getArtist } = albumContext;
const artistContext = useContext(ArtistContext);
const { artist, getselectedArtist } = artistContext;
const handleSelect = (artist_id) => {
getArtist(artist_id);
getselectedArtist(artist_id);
};
return (
<>
<div
style={{ border: "1px solid black", margin: "10px", padding: "5px" }}
>
<p>{item.name}</p>
<button type="button">Edit</button>
<button type="button">Delete</button>
<button type="button" onClick={() => handleSelect(item.id)}>
Select
</button>
</div>
</>
);
};
export default Artist;
第二个是 ALBUMSTATE,我在其中调用函数 getArtist 来调度并获取该 selected 艺术家 的所有专辑
import React, { useReducer } from "react";
import AlbumContext from "./AlbumContext";
import AlbumReducer from "./AlbumReducer";
import { GET_ARTIST, ADD_ALBUM, VALIDATE_FORM } from "../../types";
const AlbumState = (props) => {
const initialState = {
albums: [],
errorform: false,
selectedartist: "",
};
const [state, dispatch] = useReducer(AlbumReducer, initialState);
//-----METHODS-----//
const addAlbum = (album) => {
dispatch({
type: ADD_ALBUM,
payload: album,
});
};
const setError = (error) => {
dispatch({
type: VALIDATE_FORM,
payload: error,
});
};
const getArtist = (id) => {
dispatch({
type: GET_ARTIST,
payload: id,
});
};
return (
<AlbumContext.Provider
value={{
selectedartist: state.selectedartist,
albums: state.albums,
errorform: state.errorform,
addAlbum,
setError,
getArtist,
}}
>
{props.children}
</AlbumContext.Provider>
);
};
export default AlbumState;
这是 ALBUMREDUCER
import { GET_ARTIST, ADD_ALBUM, VALIDATE_FORM } from "../../types";
export default (state, action) => {
switch (action.type) {
case ADD_ALBUM:
return {
...state,
albums: [action.payload, ...state.albums],
};
case VALIDATE_FORM:
return {
...state,
errorform: action.payload,
};
case GET_ARTIST:
console.log(action.payload);
return {
...state,
selectedartist: action.payload,
albums: state.albums.filter(
(album) => album.artist_creator === action.payload
),
};
return {
...state,
selectedartist: action.payload,
};
default:
return state;
}
};
这里有两件事你需要考虑
- 您正在使用 React.strictMode,其中 React 在开发期间有意调用分派方法两次。根据反应文档
Strict mode can’t automatically detect side effects for you, but it can help you spot them by making them a little more deterministic. This is done by intentionally double-invoking the following functions:
- Class component constructor, render, and shouldComponentUpdate methods
- Class component static getDerivedStateFromProps method
- Function component bodies
- State updater functions (the first argument to setState)
- Functions passed to useState, useMemo, or useReducer
- 其次,您没有附加任何带有艺术家的专辑,因此您的每张专辑的 artist_creator 始终为空,当您尝试基于它进行过滤时,将 return 一个空数组
case GET_ARTIST:
console.log(action.payload, state.albums, "getArtistalbum");
return {
...state,
selectedartist: action.payload,
albums: state.albums.filter(
album => album.artist_creator === action.payload
) // This returns empty array
};
这里最后要注意的是,您正在使用过滤后的 redux 覆盖原始相册数组,因此您的所有相册数据都将被删除。而是为过滤的项目保留一个单独的键并像
一样过滤它个案GET_ARTIST: console.log(action.payload, state.albums, "getArtistalbum"); return{ ...状态, 选定的艺术家:action.payload, 所选专辑:state.albums.filter( 专辑 => album.artist_creator === action.payload ) // 从所有相册中筛选出的选定相册的不同键 };