我正在构建一个简单的CRUD笔记应用程序,我在使用简单的POST和DELETE api调用创建和删除笔记后让子组件更新时遇到问题 .
这是包含简单表单的父组件和用于呈现提交的注释的子组件 <NotepadsShowView />
.
class AuthenticatedHomeView extends Component {
_handleSubmit(e) {
e.preventDefault()
const { dispatch } = this.props
const data = {
title: this.refs.title.value,
description: this.refs.description.value,
private: this.refs.private.checked
}
dispatch(Actions.createNotepad(this.props.currentUser.id, data))
this._resetForm()
}
_resetForm() {
this.refs.title.value = ''
this.refs.description.value = ''
this.refs.private.checked = true
}
render() {
return (
<div>
<form onSubmit={::this._handleSubmit}>
{/* form removed for clarity */}
</form>
<NotepadsShowView/>
</div>
)
}
}
和 NotepadsShowView
子组件:
class NotepadsShowView extends Component {
componentWillMount() {
const { dispatch, currentUser } = this.props
dispatch(Actions.fetchNotepads(currentUser.id))
}
_renderEachOwnedNotepad() {
const { ownedNotepads } = this.props
return ownedNotepads.map((notepad, i) => {
return <NotepadShowView key={notepad.id} {...notepad} {...this.props}/>
})
}
render() {
const { isFetchingNotepads } = this.props
const notepads = this._renderEachOwnedNotepad()
if (isFetchingNotepads || notepads.length == 0) return null
return (
<ul className="notepads-container">
{notepads}
</ul>
)
}
}
const mapStateToProps = (state) => ({
isFetchingNotepads: state.notepads.fetching,
currentUser: state.session.currentUser,
ownedNotepads: state.notepads.ownedNotepads,
sharedNotepads: state.notepads.sharedNotepads
})
export default connect(mapStateToProps)(NotepadsShowView)
这是动作创建者:
const Actions = {
createNotepad: (userId, data) => {
return dispatch => {
httpPost(`/api/v1/users/${userId}/notepads`, {data: data})
.then(data => {
dispatch({
type: CONSTANTS.NOTEPADS_CREATED,
notepad: data
})
})
.catch(error => {
error.response.json()
.then(json => {
dispatch({
type: CONSTANTS.NOTEPADS_CREATE_ERROR,
errors: json.errors,
})
})
})
}
},
fetchNotepads: (userId) => {
return dispatch => {
dispatch({
type: CONSTANTS.NOTEPADS_FETCHING
})
httpGet(`/api/v1/users/${userId}/notepads`, {id: userId})
.then(data => {
dispatch({
type: CONSTANTS.NOTEPADS_RECEIVED,
notepads: data.notepads
})
})
.catch(error => {
error.response.json()
.then(json => {
dispatch({
type: CONSTANTS.NOTEPADS_ERRORS,
errors: json.error
})
})
})
}
},
deleteNotepad: (userId, notepadId) => {
return dispatch => {
httpDelete(`api/v1/users/${userId}/notepads/${notepadId}`, {id: notepadId})
.then(data => {
dispatch({
type: CONSTANTS.NOTEPADS_OWNED_DELETE,
id: notepadId
})
})
}
},
}
这是减速器:
const initialState = {
ownedNotepads: [],
fetching: true,
}
export default function reducer(state = initialState, action = {}) {
switch (action.type) {
case CONSTANTS.NOTEPADS_FETCHING:
return {
...state,
fetching: true,
}
case CONSTANTS.NOTEPADS_RECEIVED:
return {
...state,
fetching: false,
ownedNotepads: action.notepads
}
case CONSTANTS.NOTEPADS_CREATED:
return {
...state,
ownedNotepads: [
...state.ownedNotepads,
{
id: action.id,
title: action.title,
description: action.description,
private: action.private
}
]
}
case CONSTANTS.NOTEPADS_OWNED_DELETE:
const index = state.ownedNotepads.findIndex(note => note.id === action.id)
return {
...state,
ownedNotepads: [
...state.ownedNotepads,
state.ownedNotepads.slice(0, index),
state.ownedNotepads.slice(index + 1)
]
}
default:
return state
}
}
用户提交一个新的记事本,触发POST api呼叫 . 服务器返回新的记事本,reducer将记事本添加到Redux状态 . 没问题 . 但是,当创建记事本时,记事本道具未定义,并且子UI组件中未显示新的记事本 . 他们不知道更新,我认为这是因为我没有处理状态更新 .
我在上面使用 componentWillMount
( cWM
)来获取初始渲染之前更新的记事本状态 . 我假设我应该使用 componentWillReceiveProps
但是我知道如果我发送 fetchNotepads
动作会有一个无限循环,因为 cWM
中的发送将再次运行 .
我的问题是当Redux状态发生变化时如何更新组件道具?我必须使用组件状态吗?生命周期方法怎么样?