当我试图访问react组件中的存储时,@connect工作得很好。但我该如何在其他代码中访问它呢。例如:让我们说我想使用授权令牌来创建我的axios实例,可以在我的应用程序中全局使用,实现这一点的最佳方法是什么?

这是我的api。js

// tooling modules
import axios from 'axios'

// configuration
const api = axios.create()
api.defaults.baseURL = 'http://localhost:5001/api/v1'
api.defaults.headers.common['Authorization'] = 'AUTH_TOKEN' // need the token here
api.defaults.headers.post['Content-Type'] = 'application/json'

export default api

现在我想从我的商店访问一个数据点,这是什么样子,如果我试图在一个react组件中使用@connect获取它

// connect to store
@connect((store) => {
  return {
    auth: store.auth
  }
})
export default class App extends Component {
  componentWillMount() {
    // this is how I would get it in my react component
    console.log(this.props.auth.tokens.authorization_token) 
  }
  render() {...}
}

有什么见解或工作流模式吗?


当前回答

对于TypeScript 2.0,它看起来是这样的:

MyStore.ts

export namespace Store {

    export type Login = { isLoggedIn: boolean }

    export type All = {
        login: Login
    }
}

import { reducers } from '../Reducers'
import * as Redux from 'redux'

const reduxStore: Redux.Store<Store.All> = Redux.createStore(reducers)

export default reduxStore;

MyClient.tsx

import reduxStore from "../Store";
{reduxStore.dispatch(...)}

其他回答

像@sanchit一样,如果您已经全局定义了axios实例,那么提议的中间件是一个很好的解决方案。

你可以创建一个这样的中间件:

function createAxiosAuthMiddleware() {
  return ({ getState }) => next => (action) => {
    const { token } = getState().authentication;
    global.axios.defaults.headers.common.Authorization = token ? `Bearer ${token}` : null;

    return next(action);
  };
}

const axiosAuth = createAxiosAuthMiddleware();

export default axiosAuth;

像这样使用它:

import { createStore, applyMiddleware } from 'redux';
const store = createStore(reducer, applyMiddleware(axiosAuth))

它将在每个操作上设置令牌,但您只能侦听例如更改令牌的操作。

用钩子做。我遇到了类似的问题,但我使用的是带有钩子的react-redux。我不想在我的界面代码(例如,react组件)中添加大量专门用于从商店检索/向商店发送信息的代码。相反,我希望使用具有通用名称的函数来检索和更新数据。我的路径是把应用程序的

const store = createSore(
   allReducers,
   window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
 );

并在const之前添加export,并在store.js中添加常用的react-redux导入。文件。然后,我在应用程序级别导入到index.js,然后我用通常的import {store}从“./store.js”导入到index.js,然后子组件使用useSelector()和useDispatch()钩子访问商店。

为了在非组件前端代码中访问存储,我使用了类似的导入(即从“../../store.js”导入{store}),然后使用store. getstate()和store.js。分派({*action goes here*})来处理存储的检索和更新(呃,发送动作到)。

我也遇到过类似的问题——我想建立一个全局Axios配置,可以从React内部的任何地方访问(组件,组件外部,thunk action内部..)

我最终编写了一个返回配置对象的thunk。好处是,由于getState(),坦克可以访问存储,所以您不必重新发明轮子。也许这个解决方案可以帮助某些人;)

1. 铛

export const getAxiosConfig = (payload) => {
      return (dispatch, getState) => {
      
      const { app } = getState();
    
      const axiosConfig: AxiosRequestConfig = {
        baseURL: `${process.env.BACKEND_API}`,
        headers: {
          Authorization: `Bearer ${app.token}` 
        }
      };

      return axiosConfig;
    }
 }

2. 获取配置

const axiosConfig = dispatch(getAxiosConfig(null));

3.使用config调用API

const {data} = await axios.get(/resource/${resourceId}, axiosConfig );

你可以根据我如何访问非反应组件的商店使用中间件?:

中间件

function myServiceMiddleware(myService) {
  return ({ dispatch, getState }) => next => action => {
    if (action.type == 'SOMETHING_SPECIAL') {
      myService.doSomething(getState());
      myService.doSomethingElse().then(result => dispatch({ type: 'SOMETHING_ELSE', result }))
    }
    return next(action);
  }
}

使用

import { createStore, applyMiddleware } from 'redux'
const serviceMiddleware = myServiceMiddleware(myService)
const store = createStore(reducer, applyMiddleware(serviceMiddleware))

进一步阅读:Redux Docs >中间件

从调用createStore的模块导出存储。然后您可以放心,它将被创建并且不会污染全局窗口空间。

MyStore.js

const store = createStore(myReducer);
export store;

or

const store = createStore(myReducer);
export default store;

MyClient.js

import {store} from './MyStore'
store.dispatch(...)

或者如果你使用默认

import store from './MyStore'
store.dispatch(...)

对于多个存储用例

如果需要一个存储的多个实例,可以导出一个工厂函数。 我建议将其设置为异步(返回承诺)。

async function getUserStore (userId) {
   // check if user store exists and return or create it.
}
export getUserStore

在客户端(在异步块中)

import {getUserStore} from './store'

const joeStore = await getUserStore('joe')