如何在Redux Saga中使用React Hook?

3

我的解决方案


我正在为我的应用程序设置语言,但我遇到了一个问题。

我使用 React.useContext() 来设置语言。但当我在 saga 的提示中修复它时,它会记录以下错误:

[错误:无效的钩子调用。钩子只能在函数组件的主体内调用。这可能是由于以下原因之一引起的:

  1. 您可能有不匹配版本的 React 和呈现器(例如React DOM)
  2. 您可能正在违反钩子规则
  3. 您可能有多个副本的 React 在同一个应用程序中。有关如何调试和解决此问题的提示,请参见 https://reactjs.org/link/invalid-hook-call]

那么我是否可以在saga中使用它?如果是, 我应该如何使用它?如果不行, 你能给我建议一个解决方案吗?


最终的解决方案是来自saga中的props message。


这是我 'toast.js' 文件中的一个函数:

export function toastLoginSuccess() {
  ToastAndroid.show(
    LANGUAGES.toastLoginSuccess,
    ToastAndroid.SHORT,
    ToastAndroid.TOP,
  );
}

采用以下方式导入语言文件: import * as LANGUAGES from '../asset/language';

toastLoginSuccess 的值为export const toastLoginSuccess = '登录成功!';

我希望将其更改为const LANGUAGES = React.useContext(LanguageContext).language;

Saga是类似于以下结构的文件:

export function* fetchSigninSaga(action) {
  try {
    // ...
    yield Toast.toastLoginSuccess())
  } catch (error) {
    // ...
    yield Toast.toastLoginFail();
  }
}

1
React hooks只能在函数组件和其他React hooks中调用。你不能直接从saga中调用React hook。 - Drew Reese
你有解决我的问题的方案吗,@DrewReese? 我已经尝试修复它大约两个星期了,但仍然束手无策。 - Zuet
或者我应该使用另一种方式来设置应用的语言? - Zuet
很遗憾,我对sagas并不熟悉,甚至无法做出有根据的猜测。 - Drew Reese
最终解决方案是来自saga的props消息。 - Zuet
3个回答

5

您需要首先在saga中注入上下文,以下是实现方式:

import createSagaMiddleware from "redux-saga";

const userService = createUserService(...);

const sagaMiddleware = createSagaMiddleware({
    context: LanguageContext
});

sagaMiddleware.run(rootSaga);

一旦你完成注入,你可以按以下方式使用它:

import { getContext } from "redux-saga/effects";

export function* loadUsersSagas(action) {
    const languageContext = yield getContext("languageContext");
    const language = yield languageContext.getLanguage();
    ...
}

如果您想了解更多信息,您可以查看getContext


谢谢。我计划从saga中提取消息。因为我将语言状态保存到AsyncStorage中,所以修复起来需要很长时间。我会尝试你的方法。 - Zuet
如何在saga中使用自定义hooks? - user18209107

1
如果你想在React Saga生成器函数中使用React Hook(不仅限于此示例),你需要创建一个函数来在saga生成器函数之外运行你的hook,然后在saga生成器函数内调用该函数。
示例
const success = ()=> { 
   // your hook or any other hook 
   Toast.toastLoginSuccess()
}
const failed = ()=> { 
   // your hook or any other hook
   Toast.toastLoginFail()
}



你可以随后调用你的函数。
export function* fetchSigninSaga(action) {
  try {
    // ...
    yield success()
  } catch (error) {
    // ...
    yield failed();
  }
}

0

我的解决方案是

export function toastLoginSuccess() {
  AsyncStorage.getItem('language').then(value => {
    switch (value) {
      case 'en':
        return ToastAndroid.show(
          English.toastLoginSuccess,
          ToastAndroid.SHORT,
          ToastAndroid.TOP,
        );

      default:
        return ToastAndroid.show(
          Vietnamese.toastLoginSuccess,
          ToastAndroid.SHORT,
          ToastAndroid.TOP,
        );
    }
  });
}

当我改变LanguageContext时,我会在AsyncStorage上保存语言状态。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接