Javascript state.map在发送时不是一个函数
我有一个react组件,它使用useReducer钩子处理动态文本字段的添加和删除。 预计工作如下: 类型“add”将用一个或多个空对象追加当前状态。添加按钮的onClick事件 类型“remove”将从状态数组中删除对象。删除按钮的onClick事件 使用状态变量上的映射函数渲染字段。 但是当我尝试使用add/remove分派时,state.map函数将变得未定义。 任何形式的帮助都是非常感激的 代码片段Javascript state.map在发送时不是一个函数,javascript,reactjs,react-hooks,frontend,Javascript,Reactjs,React Hooks,Frontend,我有一个react组件,它使用useReducer钩子处理动态文本字段的添加和删除。 预计工作如下: 类型“add”将用一个或多个空对象追加当前状态。添加按钮的onClick事件 类型“remove”将从状态数组中删除对象。删除按钮的onClick事件 使用状态变量上的映射函数渲染字段。 但是当我尝试使用add/remove分派时,state.map函数将变得未定义。 任何形式的帮助都是非常感激的 代码片段 export default function Create(props) {
export default function Create(props) {
const initialState = [{}];
function reducer(state, action) {
switch (action.type) {
case 'add':
state = {...state}
console.log(state)
return state;
case 'remove':
return state;
default:
throw new Error();
}
}
const {dialogOpen, data} = {...props}
const [open, setOpen] = React.useState(false);
const [state, dispatch] = React.useReducer(reducer, initialState)
return (
<div>
{
state.map(() => {
return (
<div style={{display: "flex", alignItems: "center"}}>
<ApplicationBudget/>
<IconButton style={{marginLeft: 10}} onClick={() => dispatch({type: 'remove'})}
aria-label="delete" margin={{margin: 2}}>
<DeleteOutlined/>
</IconButton>
<IconButton aria-label="add" onClick={() => dispatch({type: 'add'})}
margin={{margin: 1}}>
<Add/>
</IconButton>
</div>
)
})
}
</div>
);
}
您的初始状态是一个数组:
initialState = [{}]
因此state.map作为数组的原型有一个map方法
但是,在减速器中,返回一个对象:
state = {...state}
您的对象没有贴图方法
这里有两个问题:
您不应该修改state变量,而应该让它保持不变,并返回一个新的状态。一种常见的工作方式是将当前状态扩展到返回状态。
您需要保持类型稳定,因此返回数组,而不是对象。
例如:
function reducer(state, action) {
switch (action.type) {
case 'add':
return [...state, "new entry"];
}
}
更新:我为您添加了一个最小的示例。它有一个具有两个动作的减速器。一个和你有同样错误行为的人,一个正常工作的人
功能应用程序{
const reducer=状态,action=>{
开关动作类型{
案例添加-断开:{
返回{…状态};
}
案例添加工作:{
返回[…状态,…操作.有效负载];
}
默认值:{
抛出新的错误;
}
}
};
const[state,dispatch]=React.usereducer,['a','b'];
回来
{state.maps=>{s}
分派{type:'add breaked',payload:'C'}}>add breaked
分派{type:'add working',payload:'C'}}>add working
;
}
ReactDOM.render、document.getElementByIdapp;
谢谢fjc的帮助。
以下面的解决方案结束
export default function Create(props) {
const initialState = [{}];
function reducer(state, action) {
switch (action.type) {
case 'add':
return [...state, ...action.payload]
case 'remove':
let newState = [...state]
newState.splice(action.payload, 1)
return newState
default:
throw new Error();
}
}
const {dialogOpen, data} = {...props}
const [open, setOpen] = React.useState(false);
const [state, dispatch] = React.useReducer(reducer, initialState)
return (
<div>
{
state.map((budget, index) => {
return (
<div key={index} style={{display: "flex", alignItems: "center"}}>
<ApplicationBudget/>
<IconButton style={{marginLeft: 10}}
onClick={() => dispatch({type: 'remove', payload: index })}
aria-label="delete" margin={{margin: 2}}>
<DeleteOutlined/>
</IconButton>
<IconButton aria-label="add"
onClick={() => dispatch({type: 'add', payload: [{}]})}
margin={{margin: 1}}>
<Add/>
</IconButton>
</div>
)
})
}
</div>
);
}