React-Native普通函数调用useSelector报Invalid hook call错误怎么解决
错误产生原因
React Hook有严格的调用规则,useSelector 属于Redux提供的自定义Hook,必须满足以下调用条件才可以正常执行:
- 只能在React函数组件/自定义Hook的顶层作用域调用
- 不能在普通JS函数、事件回调、异步逻辑、循环/条件判断内部调用
你写的authStage_getToken是普通工具函数,而且是在onButtonPress这个点击事件回调里触发调用的,完全不符合Hook的调用规则,因此触发Invalid hook call报错。而DetailsScreen里的useSelector是在函数组件的顶层调用,符合规则所以可以正常运行。
修复方案
方案1:把需要的Redux状态从组件传入工具函数(最推荐,符合单向数据流逻辑)
直接修改authStage_getToken,不要在内部调用Hook,改为接收username作为入参:
// authentication.js 修改后 export const authStage_getToken = (username) => { const password = 'testingEncoding'; const credentials = base64.encode(username + ':' + password); console.log('authStage_getToken encoded credentials:', credentials); return credentials; }
然后在LoginScreen组件内先拿到username再传入函数:
// LoginScreen.js 修改onButtonPress逻辑 const onButtonPress = () => { if (!username || username === '') { setValidationError("Username cannot be blank."); return; } changeLogin({username:username,password:password}); console.log('Before triggering getToken...'); // 直接把当前组件拿到的username传入 const result = authStage_getToken(username); console.log('After triggering getToken, result: ', result); }
方案2:非组件场景直接读取store实例
如果你的工具函数会在大量非组件场景调用,不方便每次传参,可以在你初始化Redux store的文件里把store实例导出,然后在工具函数里直接调用store.getState()拿状态:
// store初始化文件(示例,比如store.js) import { configureStore } from '@reduxjs/toolkit'; import authenticationReducer from './reducers/authentication'; export const store = configureStore({ reducer: { authentication: authenticationReducer, // 其他reducer } })
修改authentication.js:
// authentication.js 修改后 import { store } from '../路径/到/你的/store.js'; export const authStage_getToken = () => { // 直接通过getState拿全局状态,不需要用Hook const username = store.getState().authentication.username; const password = 'testingEncoding'; const credentials = base64.encode(username + ':' + password); console.log('authStage_getToken encoded credentials:', credentials); return credentials; }
该方案不需要修改调用侧代码,注意getState是同步拿到调用瞬间的状态快照,不会自动监听状态变化,如果需要响应状态更新还是要在组件内使用useSelector。
内容的提问来源于stack exchange,提问作者Leland T Long
相关产品推荐
相关产品推荐

