React Native跨类调用函数时this指向问题求助
解决React封装请求函数时的上下文
this问题 你的核心问题在于:你创建了一个独立的KoHttpRequest组件实例来调用请求方法,但这个实例的this和调用它的组件完全无关——它没法访问调用组件的state、setState或者navigation props。而且这个组件本身不需要渲染UI,其实完全没必要做成React组件类,改成纯工具函数会更简洁,也更容易解决上下文问题。
方案1:改成工具函数,传入所需上下文
把KoHttpRequest改成纯函数,将调用组件的this(或者需要的特定方法)作为参数传递进去,这样函数就能直接使用调用组件的上下文了:
重构Functions.js:
// Functions.js export const postRequest = async (url, json, accessToken, componentContext) => { // 使用传入的组件上下文调用setState componentContext.setState({ loaded: false, validatingAction: false }); try { const response = await fetch(url, { method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', 'Authorization': 'Bearer '.concat(accessToken) }, body: json }); if (response.ok) { // 调用组件的fetchData方法 await componentContext.fetchData(); componentContext.setState({ loaded: true }, () => { componentContext.userIsValidatingAnAction(); setTimeout(() => { componentContext.setState({ validatingAction: false }); }, 1000); }); } else { // 正确获取error-reason header(原代码的headers.map写法有误) const errorReason = await response.headers.get('error-reason') || '未知错误'; // 使用组件的navigation跳转 componentContext.props.navigation.navigate('Accueil', { failedAction: true, errorReason: `${errorReason} URL : ${response.url}` }); } } catch (error) { console.error('请求失败:', error); } };
在调用组件中使用:
import { postRequest } from '../Components&Functions/Koust.js'; createNewInvoice = () => { postRequest( 'https://koupp.com/apex/rest/mobile/facture', JSON.stringify({ type:'C', numero: this.state.invoiceNumber, date_liv: this.state.pickedDate, provider_id: this.state.selectedProvider }), this.state.accessToken, this // 把当前组件的this作为上下文传进去 ); };
方案2:解耦依赖,只传需要的方法(更推荐)
如果不想传递整个组件的this,可以只传递函数需要用到的特定方法,这样更解耦,也避免依赖整个组件实例:
重构Functions.js:
// Functions.js export const postRequest = async (url, json, accessToken, handlers) => { const { setState, fetchData, userIsValidatingAnAction, navigate } = handlers; setState({ loaded: false, validatingAction: false }); try { const response = await fetch(url, { /* 配置不变 */ }); if (response.ok) { await fetchData(); setState({ loaded: true }, () => { userIsValidatingAnAction(); setTimeout(() => setState({ validatingAction: false }), 1000); }); } else { const errorReason = await response.headers.get('error-reason') || '未知错误'; navigate('Accueil', { failedAction: true, errorReason: `${errorReason} URL : ${response.url}` }); } } catch (error) { console.error('请求失败:', error); } };
在调用组件中使用:
createNewInvoice = () => { postRequest( 'https://koupp.com/apex/rest/mobile/facture', JSON.stringify({ /* 数据不变 */ }), this.state.accessToken, { setState: this.setState.bind(this), fetchData: this.fetchData.bind(this), userIsValidatingAnAction: this.userIsValidatingAnAction.bind(this), navigate: this.props.navigation.navigate.bind(this.props.navigation) } ); };
为什么你的原始方案不行?
当你执行new KoHttpRequest().postRequest()时,你创建了一个全新的KoHttpRequest组件实例——它的this指向自己,和调用它的组件没有任何关联。这个空组件没有你需要的state、setState,也没有navigation props,所以自然无法执行那些操作。
额外优化建议
- 把重复的请求头配置抽成常量,避免每次请求重复写;
- 可以考虑用axios替代原生fetch,它的错误处理和响应解析会更简洁;
- 如果多个组件都需要这类请求逻辑,也可以考虑封装成自定义Hook(如果你的项目使用React Hooks),比如
useHttpRequest。
内容的提问来源于stack exchange,提问作者GODAL Tristan
相关产品推荐
相关产品推荐

