React/Redux中Uncaught TypeError: Cannot read property 'then' of undefined问题
解决 "Cannot read property 'then' of undefined" 错误
这个错误的根源很明确:你的updateRecipe action creator没有返回一个Promise,所以当你在组件里调用this.props.updateRecipe().then(...)时,updateRecipe()返回的是undefined,自然无法调用.then()方法。
问题出在你的Action文件里
看一下你的updateRecipe函数:
const updateRecipe = (data) => { return dispatch => { axios.put(`http://localhost:8009/api/v1/recipes/${data.id}`, data) .then(() => dispatch( recipeUpdated(data) )).catch( error => { error} ) } }
这里你在dispatch的回调里调用了axios.put,但没有把这个axios请求的Promise返回出去。Thunk允许你返回一个Promise,这样组件就能在调用action之后链式调用.then()。
修改方案:返回axios的Promise链
只需要把axios.put的调用return出去,或者把整个dispatch函数里的Promise返回:
const updateRecipe = (data) => { return dispatch => { // 这里加上return,把axios的Promise返回给调用者 return axios.put(`http://localhost:8009/api/v1/recipes/${data.id}`, data) .then(() => { dispatch(recipeUpdated(data)); // 如果需要在组件里拿到返回的recipe,也可以在这里return data return data; }).catch( error => { // 记得把错误抛出去,这样组件的.catch才能捕获到 throw error; }) } }
这样修改后,this.props.updateRecipe()就会返回一个Promise,你就能正常调用.then()和.catch()了。
额外的优化建议
- 错误处理:原来的catch块里只是写了
error,没有任何处理,现在改成throw error,这样组件里的错误回调才能捕获到错误信息。 - 组件里的loading状态:成功后你设置了
loading: true,这应该是笔误,应该改成loading: false,否则表单会一直处于加载状态:.then( ()=>{ console.log("see me") this.setState({ done : true, loading: false}) // 这里把loading改成false } - 过时生命周期替换:
componentWillReceiveProps已经被标记为过时,建议换成componentDidUpdate或者getDerivedStateFromProps,不过这不是当前问题的核心,只是长期维护的优化点。
验证其他部分
你的reducer逻辑看起来是正确的,当RECIPE_UPDATED触发时,会正确更新对应id的recipe。组件里的表单逻辑也没问题,只要action返回了Promise,.then()就能正常执行。
内容的提问来源于stack exchange,提问作者val15
相关产品推荐
相关产品推荐

