我的来源:https://codesandbox.io/s/x91zl9v78p
我尝试编辑标题和内容,但是第一次,内容没有被修改,只有标题被修改了。
从第二个开始效果很好。
为什么会出现此错误?
reducers.js:
case UPDATE_POST:
return state.map(
post => (post.id === action.id ? Object.assign({}, post, action) : post)
);
而且,有没有一种方法可以不使用object.assign来使用扩展运算符?
答案 0 :(得分:2)
之所以会发生这种情况,是因为您的Item组件的结构带有空字符串,因此,当您编辑标题输入时,状态会更新,并且如果您不编辑内容输入,它将保持为空。
components / List / items.jsx
class Item extends Component {
constructor(props) {
super(props);
this.state = {
isEdit: false,
title: this.props.title,
content: this.props.content
};
}
//...
}
并避免Object.assign
reducers / post.jsx
case UPDATE_POST:
return state.map(
post => (post.id === action.id ? { ...post, ...action } : post)
);
这将克隆post
个道具,并合并action
个道具。
答案 1 :(得分:1)
由于您将标题和内容的初始值存储在道具中,因此您需要通过实现
将初始Item
组件状态值同步到道具
static getDerivedStateFromProps({ title, content }) {
return {
title, content
}
}
否则,如果用户不触摸字段(例如内容),则代码将使用默认状态值,该值为空字符串。
而且,有没有一种方法我可以不用 object.assign?
case UPDATE_POST:
return state.map(
post => (post.id === action.id ? {...post, ...action} : post)
);
此外,通过将整个操作分散到帖子中,您正在污染带有附加属性type
的帖子对象。考虑使用payload
对象代替传递更新的帖子。
export function updatePost(id, title, content) {
return {
type: UPDATE_POST,
payload: {
id,
title,
content
}
};
}
然后散布有效载荷
case UPDATE_POST:
return state.map(
post => (post.id === action.payload.id ? {...post, ...action.payload} : post)
);
答案 2 :(得分:1)
因为item.jsx文件中的this.state.title
和this.state.content
仅在更改了输入get的情况下才更新,如果其中一个输入未更改,则this.state.title or this.state.content
都是空字符串。在将项目添加到列表后,this.props.title
和this.props.content
可用,但是this.state.title
和this.state.content
最初在组件中定义为“”字符串。因此可以在编辑集this.state.title = this.props.title
和this.state.content = this.props.content
上将defaultvalue用作this.props.tile和this.props.content,然后它将起作用。
答案 3 :(得分:0)
也许可以通过像这样在args函数中使用它:
export default function Post(state = initialState, {type, ...post}) {
switch (type) {
case ADD_POST:
return [ ...state, post ];
case REMOVE_POST:
return state.filter(({ id }) => id !== post.id);
case UPDATE_POST:
return state.map( p => (p.id === post.id ? post : p) );
default:
return state;
}
}