2017-08-19 33 views
0

问题回调:遗漏的类型错误:无法读取属性“然后”未定义

的我在终极版异步函数(终极版的thunk),在终极版店内设置的值。它在我的应用程序中被多次使用,但是,我希望在使用redux函数设置的新值运行redux函数后发生不同的事情。似乎是一个回调的好理由,对吧?所以,我想这样做只是这一点,但我得到了以下错误:在尝试修复

认为的原因可能是,虽然终极版功能分派行动,这不是

Uncaught TypeError: Cannot read property 'then' of undefined

逻辑实际上没有任何回报。因此,我在redux函数中添加了returns,认为该函数会将某些内容返回给调用它的组件,这将解决我收到的错误。没有运气。


问:

有谁知道我怎么能后执行功能异步Redux的函数(终极版的thunk)运行,并完成设定了Redux存储一个新的价值?


我最近尝试解决

组件

import {fetchUser} from './../actions/index.js'; 

class MyComponent extends React.Component { 

    constructor(props) { 
    super(props); 
    } 

    componentDidMount() { 
    // Attempt #1: this.props.fetchUserData()); // originally I attempted just running one function and then the rest without a callback but the new value was not set in redux store before the next function that needed it ran 
    // Attempt #2: this.props.fetchUserData().then(function() => { // I also tried running just a standard .then(function() 
    // Attempt #3: (line below) 
    this.props.fetchUserData().then((resultFromReduxFunction) => { 
     console.log("fetchUserData result = " + resultFromReduxFunction); 

     // do some stuff with the new data 
     console.log("this.props.reduxData.userHairColor = " + this.props.reduxData.userHairColor); 
     console.log("this.props.reduxData.userHeight = " + this.props.reduxData.userHeight); 
    }); 
    } 
} 

function mapStateToProps(state) { 
    return { 
     reduxData: state.user 
    }; 
} 

function matchDispatchToProps(dispatch) { 
    return bindActionCreators({ 
     fetchUserData: fetchUserData 
    }, dispatch) 
} 

export default connect(mapStateToProps, matchDispatchToProps)(MyComponent); 

行动造物主

export const set = (idToSet, payloadToSet) => { 
    return { 
    type: 'SET', 
    id: idToSet, 
    payload: payloadToSet 
    } 
} 

export const fetchUserData = (callbackFunction) => { 
    console.log("fetchUserData triggered..."); 
    return (dispatch, getState) => { 
    firebase.auth().onAuthStateChanged(function (user) { 
     if (!user) { 
     console.log("no user logged in"); 
     return false // Added in attempt to fix callback 
     } else { 
     // fetch some more user data 
     firebase.database().ref().child('users').child(user.uid).on('value', function(snapshot) { 
      var userHairColor = snapshot.child(userHairColor).val(); 
      var userHeight = snapshot.child(userHeight).val(); 
      dispatch(set('userHairColor', userHairColor)); 
      dispatch(set('userHeight', userHeight)); 
      return true // Added in attempt to fix callback 
     }) 
     } 
    }) 
    } 
} 

终极版商店

const initialState = { 
    userHairColor: "", 
    userHeight: "" 
} 

export default function (state=initialState, action) { 
    switch(action.type) { 
    case 'SET': 
     return { 
     ...state, 
     [action.id]: action.payload 
     } 
    default: 
     return { 
     ...state 
     } 
    } 
} 

提前感谢所有帮助

+0

'调度(集( 'userHairColor',userHairColor));''是一个set'行动创造者? 显示它,如果是。 – Andrew

+0

这是一个减速器,我想看到行动的创造者。 – Andrew

+0

添加了'SET'动作创建者 – Rbar

回答

1

回调会的工作,如果你真的明确地把它称为​​thunk的里面,但它确实感觉像一个反模式。

相反,您可以调度另一个可以处理任何进一步逻辑的thunk。或者,如果您需要对您的反应组件中的结果做出反应,则调度一个将修改您的redux状态的操作。这又将调用反应生命周期方法和render,您可以根据新状态对那里的更改做出反应。

要改善答案,这将有助于了解完成操作后要执行的操作。

1

要使用.then(...),你的thunk必须返回一个Promise。火力地堡的onAuthStateChanged似乎返回取消订阅的功能,而不是一个承诺,所以即使你回来,它不会让你链附加回调在你行动的创建者调用点。而且你不能从你传递给onAuthStateChanged的回调中返回,因为你在这个时候处于不同的调用栈中(它是异步的)。

你打算什么需要做的是传递一个回调函数,你的行动的创建者,它需要从数据获取的成功回调中调用。

事情是这样的:

export const fetchUserData = (callbackFunction) => { 
    return (dispatch, getState) => { 
    firebase.auth().onAuthStateChanged(function (user) { 
     if (!user) { 
     console.log("no user logged in"); 
     // You can pass false to your callback here, so that it knows the auth was unsuccessful 
     callbackFunction(false); 
     } else { 
     // fetch some more user data 
     firebase.database().ref().child('users').child(user.uid).on('value', function(snapshot) { 
      var userHairColor = snapshot.child(userHairColor).val(); 
      var userHeight = snapshot.child(userHeight).val(); 
      dispatch(set('userHairColor', userHairColor)); 
      dispatch(set('userHeight', userHeight)); 
      // Passing true so your callback knows it was a success 
      callbackFunction(true); 
     }) 
     } 
    }) 
    } 
} 

然后用它作为期望:

this.props.fetchUserData((success) => { 
    console.log("fetchUserData result = " + success); 

    // do some stuff with the new data 
    console.log("this.props.reduxData.userHairColor = " + this.props.reduxData.userHairColor); 
    console.log("this.props.reduxData.userHeight = " + this.props.reduxData.userHeight); 
}); 

有一点回调地狱会在这里,但为避免你不得不使用“promisified版”火力地堡的API,在这种情况下,这样使用你的行动的创建者什么事情都可能附加.then(...)你也可以从你的thunk返回的承诺。

+0

感谢帮助@philraj。我试过这个解决方案,但它返回以下错误:'callbackFunction不是一个函数'..任何想法为什么? – Rbar

+0

@Rbar我得看看你是如何调用'fetchUserData',但它听起来像是你传递给它究竟是不是一个函数。 – philraj

+0

@Rbar顺便说一句,即使我展示了如何做到这一点,我同意Martin Kadlec的回答,这感觉就像是反模式。查看他的答案获取更多信息。 – philraj

相关问题