我正在构建一个简单的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组件中未显示新的记事本 . 他们不知道更新,我认为这是因为我没有处理状态更新 .

我在上面使用 componentWillMountcWM )来获取初始渲染之前更新的记事本状态 . 我假设我应该使用 componentWillReceiveProps 但是我知道如果我发送 fetchNotepads 动作会有一个无限循环,因为 cWM 中的发送将再次运行 .

我的问题是当Redux状态发生变化时如何更新组件道具?我必须使用组件状态吗?生命周期方法怎么样?