React Native如何从App.js向Login组件传递设备Token?
首先,咱们拆解下你代码里的几个核心问题,这些问题不仅导致Token传不了,连普通字符串也会传递失败:
1. 错误的State更新方式
你在componentDidMount里直接给this.state.token赋值,这违反了React的状态更新规则——永远不要直接修改state,必须用this.setState()来更新,否则组件不会触发重渲染,新的Token也无法被传递下去。
修正后的componentDidMount代码:
async componentDidMount() { const token = await firebase.messaging().getToken(); // 用setState更新状态,触发组件重渲染 this.setState({ token }); this.checkPermission(); this.createNotificationListeners(); }
2. 路由初始名称不匹配
你的StackNavigator里定义的屏幕key是Login,但initialRouteName写的是LoginScreen,这会导致React Navigation找不到对应路由,直接引发渲染异常,这也是所有数据传递失败的关键原因之一。
修正路由配置:
const RootStack = createStackNavigator( { Login: { screen: Login, navigationOptions: { headerLeft: null } }, Tab: { screen: Tab, navigationOptions: { headerLeft: null } } }, { initialRouteName: 'Login' // 改为和屏幕key一致的'Login' } );
3. 无法向createAppContainer包装的组件直接传props
createAppContainer返回的组件(即你的MyApp)不会把外部传入的props透传给内部的屏幕组件,所以你直接写<MyApp token={this.state.token}>是无效的,Login组件根本拿不到这个props。
下面给你两种可行的传递方案:
方案一:使用screenProps(适合react-navigation v3/v4)
渲染MyApp时,通过screenProps传递Token:
render() { return ( <MyApp screenProps={{ token: this.state.token }} /> ); }
然后在Login组件里,通过this.props.screenProps.token获取:
export default class LoginScreen extends React.Component { // ... async Login(){ // 直接取最新的Token,不要存在state里(避免初始为空的同步问题) console.log(this.props.screenProps.token); } }
方案二:使用React Context(推荐,适配所有版本)
这种方式更灵活,尤其适合react-navigation v5+或跨多层组件传递数据的场景:
首先在App.js里创建Context:
import React from 'react'; // 创建Token上下文 const TokenContext = React.createContext();
用Provider包裹你的AppContainer:
render() { return ( <TokenContext.Provider value={this.state.token}> <MyApp /> </TokenContext.Provider> ); }
最后在Login组件里消费这个Context:
export default class LoginScreen extends React.Component { // 绑定Context类型 static contextType = TokenContext; async Login(){ // 直接通过this.context获取Token console.log(this.context); } // ...其他代码 }
关于Token传递的特殊说明
Token本质就是字符串,传递没有特殊要求,只要保证在传递时Token已经获取完成(即等待getToken异步操作结束),同时使用正确的组件通信方式即可。另外建议不要把Token存在Login组件的state里,因为App组件的Token更新后,Login组件的state不会自动同步,直接从props或Context取最新值更可靠。
内容的提问来源于stack exchange,提问作者Rémy

