【问题标题】:Redux Invalid hook callRedux 无效的钩子调用
【发布时间】:2020-04-21 02:57:35
【问题描述】:

我正在尝试在我的 React 应用程序中的组件之间交换一些数据,并尝试使用 Redux。

我真的在寻找简单的功能(存储 accesstoken,检索 accesstoken)。

我在文件夹 src/reducers/currenttokenreducer.js 中有一个文件:

const currentTokenReducer = (state, action) => {
    switch(action.type){
        case 'SETTOKEN':
            return action.payload
        case 'GETTOKEN':
            return state
        default: return null
    }
}
export default currentTokenReducer;

然后我在 src/reducers/ 中有一个 index.js:

import currentUserReducer from './currentuser.js'
import currentTokenReducer from'./currenttoken.js'
import {combineReducers} from 'redux'

const allReducers = combineReducers({
    currentUserReducer, currentTokenReducer
})
export default allReducers

终于在 index.js 中我有了:

import React from 'react';
import b2cauth from 'react-azure-adb2c';
import ReactDOM from 'react-dom';
import jwt from 'jwt-decode'
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import {createStore} from 'redux';
import allReducers from './reducers';
import {Provider} from 'react-redux'

const store = createStore(allReducers);

我猜 App/ 与 Provider 的正确封装:

b2cauth.run(() => {
    ReactDOM.render(<Provider store={store}><App /></Provider>, document.getElementById('root'));
    serviceWorker.unregister();

在 App.js 中,我触发了一个 gettoken 函数,并希望将它存储在本地状态和 redux 存储中:

componentDidMount (){


   this.gettoken();
}
async gettoken(){
const dispatch = useDispatch();
let apiurl = 'https://get.....azurewebsites.net……'
var token = await Axios.get(apiurl,{headers: { 'Content-Type': 'application/x-www-form-urlencoded' }});
this.setState({accesstoken: token.data});
dispatch (settoken(token.data));
}

settoken 定义在 src/actions/:

export const settoken = (token) => {
    return {
        type: 'SETTOKEN',
        payload: token
    };
};

当我部署它时,我得到:

未处理的拒绝(错误):无效的挂钩调用。钩子只能在函数组件的主体内部调用。这可能是由于以下原因之一: 1. 你可能有不匹配的 React 版本和渲染器(例如 React DOM) 2. 你可能违反了 Hooks 规则 3. 你可能有多个 React 副本同一个应用 请参阅 ... 了解有关如何调试和解决此问题的提示。

它指向 App.js 中的这一行:

const dispatch = useDispatch();

我做错了什么?

【问题讨论】:

  • 看起来你在类组件中调用useDispatchuseSelectoruseDispatch 是 React Hooks,只在函数组件中起作用。

标签: reactjs redux react-redux


【解决方案1】:

您是否有可能尝试在类中使用钩子 (useDispatch())?因为钩子在类中不起作用(参见:https://reactjs.org/docs/hooks-overview.html#but-what-is-a-hook)。

你仍然可以通过旧的connect(mapStateToProps)(App) 从你的道具中获得dispatch。 (见:https://react-redux.js.org/using-react-redux/connect-mapdispatch#default-dispatch-as-a-prop

【讨论】:

  • 你是对的。我需要调用 API 以便能够在 App 标签中显示外部 iframe,并且它们需要授权承载(来自 API)我认为我需要 componentDidMount() 方法并使用 setState 来触发页面的重新渲染。
  • 所以这意味着我不能使用函数 App() - 我必须坚持上课。还是我错了?在这种情况下你会建议做什么?
  • @MatnikR 我不确定我是否完全理解您的问题。如果你想从你的 App 组件中发送一些东西,为什么不在你的代码中使用 connect()(App) 从你的 props 中接收 dispatch 呢?
  • 由于我是 React 新手,我从一开始就不太清楚某些概念。肯定可以使用connect()。我将尝试以这种方式对其进行修改并返回结果 - 除非您可以为此指出一个简单的示例。在我看来,我的 POV 似乎在任何地方都被过度设计了。:-)
  • @MatnikR 我认为这是一个好的开始:react-redux.js.org/using-react-redux/… useDispatch() 是从钩子中获取 dispatch() 函数的简单方法,但它根本不是强制性的。
【解决方案2】:

你不能在类组件中使用钩子

请阅读Rules of Hooks documentation

从 React 函数组件调用 Hooks。

顺便说一句,您不需要在 reducer 中使用 GETTOKEN 操作,因为令牌已存储到存储中。

const defaultState = {value: null};

const currentTokenReducer = (state = defaultState , action) => {
  switch(action.type){
    case 'SETTOKEN':
      return {...state, value: action.payload};
    default: 
      return state;
  }
}

export default currentTokenReducer;

那么您不需要在组件内创建内部状态,因为您将从商店中检索令牌

import React, {useEffect} from 'react'; 
import { useSelector, useDispatch } from 'react-redux';
import axios from 'axios';

function AppComponent() {
  const dispatch = useDispatch();
  const token = useSelector(state => state.token.value);

  useEffect(async () => { 
    const apiurl = 'https://get.....azurewebsites.net……';
    const response = await axios.get(apiurl, ...);
    dispatch({type: 'SETTOKEN', payload: response.data});
  }, []);

  return <div>{token}</div>;
}

在这个例子中我使用了钩子useDispatchuseSelector,你可以在react-redux documentation找到更多关于这些钩子的信息

【讨论】:

    猜你喜欢
    • 2020-02-20
    • 1970-01-01
    • 1970-01-01
    • 2020-09-10
    • 2020-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-08
    相关资源
    最近更新 更多