我正在尝试更新状态对象。其中一项是键,其值是一个字符串数组。
我已经可以更新状态,但是它不会重新显示。
const initialState = {
showUpload: false,
listItems: parentDirs,
uploadPath: [],
fileList: null
};
const reducer = (state, action) => {
switch (action.type) {
case "updateListItems":
return { ...state, listItems: action.payload };
case "updatePath":
return {
...state,
uploadPath: [...state.uploadPath, action.payload]
};
default:
return state;
}
};
const [state, dispatch] = useReducer(reducer, initialState);
const pathFormat = state.uploadPath.join('/')
return (
<p>{pathFormat}</p>
)
预期的行为是更新状态对象中的数组将触发重新渲染。
答案 0 :(得分:0)
不能完全确定该数组中包含什么,但这是一个可能有用的示例。
您需要的是要定位的标识符。假设您具有以下条件:
state = {
cats: [
{
name: 'cat1',
id: 1
},
name: 'cat2',
id: 2
}
],
// ... rest of state
}
要覆盖类别2,您需要执行以下操作:
// action.type action.payload
dispatch({ type: 'updateCats', payload: {id: 2, name: 'cat3' }})
// ... and your reducer's switch returns:
case 'updateCats':
return {
...state,
cats: [...state.cats.filter( cat => id !== payload.id), action.payload]
}
您需要通过删除旧项并再次添加来重建阵列。如何执行此操作取决于您。您可以切片和拼接,或者如果顺序不重要,则示例中使用的filter方法也可以使用。
答案 1 :(得分:0)
编辑: 我想我知道您正在尝试做的事情,并且已经更新了我的回答以反映我想我所看到的-请告诉我这是否是您正在寻找什么..
您接近!只需更改您使用dispatch
的方式以及在化简器中使用action.payload
上的散布运算符即可。虽然,目前尚不清楚是使用“平面”数组还是使用对象数组-我的示例使用“平面”数组展示了“简单”方式...
类似的事情应该起作用:
const initialState = {
showUpload: false,
listItems: "parentDirs",
uploadPath: ["original","paths"],
fileList: null
};
const TYPES = {
UPDATE_LIST_ITEMS: "UPDATE_LIST_ITEMS",
UPDATE_PATH: "UPDATE_PATH",
JOIN_PATHS: "JOIN_PATHS"
}
const reducer = (state, action) => {
switch (action.type) {
case TYPES.UPDATE_LIST_ITEMS:
return {
...state,
listItems: action.payload
};
case TYPES.UPDATE_PATH:
return {
...state,
uploadPath: [...state.uploadPath, ...action.payload]
};
case TYPES.JOIN_PATHS:
return {
...state,
joinedPaths: state.uploadPath.join("/")
};
default:
return state;
}
};
function Example(props) {
const [state, dispatch] = React.useReducer(reducer, initialState);
const changeUploadPath = () => {
dispatch({type: TYPES.UPDATE_PATH, payload: ["some", "new", "paths"]})
}
const joinUploadPaths = () => {
dispatch({type: TYPES.JOIN_PATHS});
}
return(
<div>
<button onClick={joinUploadPaths}>Join Upload Paths</button>
<button onClick={changeUploadPath}>Change Upload Path</button>
<p>{state.joinedPaths}</p>
<br />
<pre>{JSON.stringify(state, null, 2)}</pre>
</div>
);
}
ReactDOM.render(<Example />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.9.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>
答案 2 :(得分:0)
我不确定您的组件为什么不重新渲染,因为您没有显示它的工作方式。因此,我所做的并建议您进一步解决问题,是在构建一个最小的,可复制的示例来测试代码。这样,我们可以看到您如何尝试解决问题,并从上下文中看到错误。
对于React项目,我喜欢使用CodeSandbox
。 Here is the link to my example
正如评论中的人们所提到的那样,我相信您遇到的问题与您分派操作的方式有关。在示例中,我展示了两种修改数组的方法。在第一个上,您处理组件内部的所有登录,并最终在action payload
上调度完整的新数组。然后在reducer
上,您必须用新的替换当前的。
在第二个示例中,我调度了一个要包含在数组中的新值。 reducer
现在负责修改state
。
处理此逻辑的最佳位置在哪里?这取决于您要完成的工作。如果逻辑将由多个组件共享,则可以将其集中在化简器中。但是,如果不同的组件将以不同的方式处理这些数组,那么分散逻辑可能是可行的方法。
我希望这会有所帮助。
答案 3 :(得分:-1)
感谢guzmonne和其他一些人提到的每个人的帮助,这实际上是调度的实现问题。感谢您的帮助。我应该对它进行更好的调试。