我正在一步步使用 React-Redux 创建角色表。 https://www.youtube.com/watch?v=cPlejG83B1Y&list=PLJ-47dnNMd_jke6l27GmEiDk5XJGcr_HE&index=5
我对 React 有模糊的概念(几年前开始教程),但我知道这段代码中不推荐使用很多东西。
我偶然发现了这个错误,但我不认为这是因为 nativeEvent 已被弃用。 在火狐浏览器上: 错误 action.payload.nativeEvent.path 未定义
关于 Opera gX : 无法读取未定义的属性(读取“1”) 类型错误:无法读取未定义的属性(读取“1”)
我认为 TraitsActions.js 中的有效负载可能定义不明确,或者以下行已被弃用,但我找不到实现它的真正方法(尝试了 Redux 文档)。 特征 => 特征.id === parseInt(action.payload.nativeEvent.path[1].id)
我读到nativeEvent 已经过时了,所以......就是这样。
减速机:
import {
ADD_TRAIT,
REMOVE_TRAIT,
UPDATE_TRAIT
} from '../constants/actionTypes';
const initialState = [];
const traitsReducer = (state = initialState, action) => {
switch(action.type){
case ADD_TRAIT:
const newTrait= {};
newTrait.trait = '';
newTrait.id = state.length;
for (let x =0; x<state.length; x++){
if(state.find(node => node.id === x) === undefined){
newTrait.id = x;
}
}
return[...state, newTrait];
case UPDATE_TRAIT:
const traitInState = state.find(
trait => trait.id === parseInt(action.payload.nativeEvent.path[1].id)
);
const traitIndex = state.indexOf(traitInState);
const traitInStateObject = new Object;
let keys;
for(keys in traitInState){
traitInStateObject[keys] = traitInState[keys];
}
traitInStateObject.trait = action.payload.target.value;
return[
...state.map((item, index)=>
index === traitIndex
? traitInStateObject
: item
)
];
case REMOVE_TRAIT:
return state.filter((trait) => trait.id !== parseInt(action.payload.nativeEvent.path[1].id))
default:
return state;
}
}
export default traitsReducer;
Trait.js 有这个元素:
<div className='trait' id={id}>
<textarea value={trait} cols='50' onChange={updateTrait}/>
<button type='button' className='red delete deleteTrait' onClick={removeTrait}>x</button>
</div>
我们在constant文件夹中得到了actionTypes.js,在actions文件夹中得到了traitsActions.js
特质行动:
import {
ADD_TRAIT,
UPDATE_TRAIT,
REMOVE_TRAIT
} from '../constants/actionTypes';
export const updateTrait = trait => ({
type: UPDATE_TRAIT,
payload: trait
})
export const addTrait = trait =>({
type:ADD_TRAIT,
payload: trait
})
export const removeTrait = trait => ({
type:REMOVE_TRAIT,
payload: trait
})
感谢您的帮助!
我建议不要尝试使用本机事件“环顾四周”并收集特征 ID 和值,而是更明确地处理所分派的操作有效负载。不使用任何事件对象,而是直接传递特征
id
和当前输入值。
示例:
export const updateTrait = (id, trait) => ({
type: UPDATE_TRAIT,
payload: { id, trait }
});
export const addTrait = () => ({
type: ADD_TRAIT
});
export const removeTrait = (id) => ({
type: REMOVE_TRAIT,
payload: id
});
const initialState = [];
const traitsReducer = (state = initialState, action) => {
switch (action.type) {
case ADD_TRAIT:
return state.concat({
trait: "",
id: state.length
});
case UPDATE_TRAIT:
if (state.some((trait) => trait.id === action.payload.id)) {
return state.map((trait) =>
trait.id === action.payload.id
? { ...trait, trait: action.payload.trait }
: trait
);
}
return state;
case REMOVE_TRAIT:
return state.filter((trait) => trait.id !== action.payload);
default:
return state;
}
};
export default traitsReducer;
const dispatch = useDispatch();
const traits = useSelector((state) => state.traits);
return (
...
<button type="button" onClick={() => dispatch(addTrait())}>
Add Trait
</button>
{traits.map(({ id, trait }) => (
<div className="trait" id={id} key={id}>
<textarea
value={trait}
cols="50"
onChange={(e) => dispatch(updateTrait(id, e.target.value))}
/>
<button
type="button"
className="red delete deleteTrait"
onClick={() => dispatch(removeTrait(id))}
>
x
</button>
</div>
))}
...
);
请注意,您正在使用“旧版”Redux 代码模式。 强烈建议您使用 Redux-Toolkit 更新和使用现代 Redux。它删除了大部分样板代码,最终您编写的代码大约减少了 50%。
示例:
traitSlice.js - 替换操作类型、操作、reducer
import { createSlice } from "@reduxjs/toolkit";
const initialState = [];
const traitsSlice = createSlice({
name: "traits",
initialState,
reducers: {
addTrait: (state) => {
state.push({
trait: "",
id: state.length
});
},
updateTrait: (state, action) => {
console.log(action.payload);
const trait = state.find((trait) => trait.id === action.payload.id);
if (trait) {
trait.trait = action.payload.trait;
}
},
removeTrait: (state, action) => {
return state.filter((trait) => trait.id !== action.payload);
}
}
});
export const { addTrait, updateTrait, removeTrait } = traitsSlice.actions;
export default traitsSlice.reducer;
import { useDispatch, useSelector } from "react-redux";
import { addTrait, removeTrait, updateTrait } from "./traitsSlice";
export default function App() {
const dispatch = useDispatch();
const traits = useSelector((state) => state.traits);
return (
<div className="App">
<div>
<button type="button" onClick={() => dispatch(addTrait())}>
Add Trait
</button>
</div>
{traits.map(({ id, trait }) => (
<div className="trait" id={id} key={id}>
<textarea
value={trait}
cols="50"
onChange={(e) =>
dispatch(
updateTrait({
id,
trait: e.target.value
})
)
}
/>
<button
type="button"
className="red delete deleteTrait"
onClick={() => dispatch(removeTrait(id))}
>
x
</button>
</div>
))}
</div>
);
}