如何让functions.js函数更新SigninScreen.js中的useState状态?
解决signInUser无法访问SigninScreen组件状态的问题
你遇到的setEmail is not a function报错,核心原因是作用域隔离——signInUser函数在独立的functions.js文件里,完全不在SigninScreen组件的作用域内,自然拿不到组件里定义的setEmail、setPassword这些状态更新函数。
工具函数的职责应该是专注于业务逻辑(比如发起登录请求),而不是直接操作组件状态,下面给你几种可行的解决方式,按推荐程度排序:
方案二:让工具函数返回结果,组件内处理状态(最推荐,解耦性最好)
这种方式把网络请求和状态更新彻底分开,工具函数只负责请求接口并返回结果,组件自己决定怎么处理状态,代码职责更清晰,也更容易复用和测试。
修改functions.js:
export async function signInUser(email, password) { console.log('Attempting to sign in'); const credentials = { email: email.toString(), password: password.toString() } const requestOptions = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(credentials) }; try { const response = await fetch('http://localhost:3000/signin', requestOptions) const data = await response.json() console.log(data) // 校验接口响应状态,失败则抛出错误 if (!response.ok) { throw new Error(data.message || '登录失败,请重试') } // 返回接口数据给组件 return data } catch (err) { console.error('登录请求出错:', err) // 把错误抛出去,让组件可以处理 throw err } }
修改SigninScreen.js的按钮点击逻辑:
<Button title="Sign in" onPress={async () => { try { const loginResult = await signInUser(email, password); // 组件内自己处理状态更新 setEmail('xaxaxaxa') // 同时可以更新Context里的用户信息 updateUserLoggerInfo(loginResult.user) console.log('登录请求完成'); } catch (err) { // 登录失败时给用户提示 alert(err.message) } }} />
方案一:把状态更新函数作为参数传入(快速临时解决)
如果只是想快速解决问题,不想大改结构,可以直接把需要的状态更新函数作为参数传给signInUser:
修改functions.js:
export async function signInUser(email, password, setEmail) { console.log('Attempting to sign in'); const credentials = { email: email.toString(), password: password.toString() } const requestOptions = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(credentials) }; const response = await fetch('http://localhost:3000/signin', requestOptions) const data = await response.json() // 现在可以调用传入的setEmail了 setEmail('xaxaxaxa') console.log(data) }
修改SigninScreen.js的按钮点击:
<Button title="Sign in" onPress={() => { signInUser(email, password, setEmail); console.log('hejjjjjj'); }} />
方案三:通过Context访问状态更新(适合全局状态场景)
既然你已经在用UserContext,如果登录相关的状态需要全局共享,可以把状态更新函数放到Context里,然后把signInUser改成自定义Hook来访问Context:
先确保appContext.js包含状态更新函数:
import { createContext, useState } from 'react' const UserContext = createContext() export function UserProvider({ children }) { const [userloggerinfo, setUserloggerinfo] = useState(null) const [email, setEmail] = useState('') const updateUserLoggerInfo = (userData) => { setUserloggerinfo(userData) } return ( <UserContext.Provider value={{ userloggerinfo, updateUserLoggerInfo, email, setEmail }}> {children} </UserContext.Provider> ) } export default UserContext
修改functions.js为自定义Hook:
import { useContext } from 'react' import UserContext from '../context/appContext.js' // 转换成自定义Hook,这样就能在内部使用useContext export function useSignIn() { const { setEmail } = useContext(UserContext) const signInUser = async (email, password) => { console.log('Attempting to sign in'); const credentials = { email: email.toString(), password: password.toString() } const requestOptions = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(credentials) }; const response = await fetch('http://localhost:3000/signin', requestOptions) const data = await response.json() setEmail('xaxaxaxa') console.log(data) return data } return signInUser }
在SigninScreen.js中使用这个Hook:
// 替换原来的signInUser导入 import { useSignIn } from '../functions/functions.js' const SigninScreen = ({ navigation }) => { const [email, setEmail] = useState('') const [password, setPassword] = useState('') const user = useContext(UserContext); // 获取Hook返回的signInUser函数 const signInUser = useSignIn() console.log(user); return ( <UserContext.Consumer> {({userloggerinfo, updateUserLoggerInfo}) => ( <View style={styles.container}> {/* ... 其他代码不变 ... */} <Spacer> <Button title="Sign in" onPress={async () => { await signInUser(email, password); console.log('hejjjjjj'); }} /> </Spacer> </View> )} </UserContext.Consumer> ) }
总的来说,方案二是最推荐的,它遵循了单一职责原则,让工具函数和组件状态解耦,代码更易维护和扩展。
内容的提问来源于stack exchange,提问作者beyondtdr
相关产品推荐
相关产品推荐

