2016-07-19 169 views
74

@connect funziona perfettamente quando sto tentando di accedere al negozio all'interno di un componente di reazione. Ma come dovrei accedervi in ​​qualche altro pezzetto di codice. Ad esempio: diciamo che voglio usare un token di autorizzazione per creare la mia istanza axios che può essere utilizzata globalmente nella mia app, quale sarebbe il modo migliore per riuscirci?Qual è il modo migliore per accedere al redux store all'esterno di un componente di reazione?

Questo è il mio 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 

Ora voglio accedere a un punto di dati dal mio deposito, ecco quello che potrebbe apparire come se stavo cercando di prenderlo all'interno di un componente reagire usando @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() {...} 
} 

Eventuali approfondimenti o modelli di flusso di lavoro disponibili?

+0

È non voglio che tu sia Axios la sostanza per vivere in un middleware redux? Sarà disponibile per tutte le tue applicazioni in questo modo –

+0

Puoi importare la classe 'api' in' App' e dopo aver ottenuto il token di autorizzazione puoi fare 'api.defaults.headers.common ['Autorizzazione'] = this.props. auth.tokens.authorization_token; ', E allo stesso tempo puoi salvarlo anche in localStorage, così quando l'utente aggiorna la pagina, puoi verificare se il token esiste in localStorage e se lo fa, puoi impostarlo., Penso che sia meglio impostare il token sul modulo API non appena lo si ottiene. –

+0

Dan Abromov fornisce un esempio nella coda di problemi qui: https://github.com/reactjs/redux/issues/916 – chrisjlee

risposta

6

È possibile utilizzare l'oggetto store restituito dalla funzione createStore (che dovrebbe essere già utilizzata nel codice nell'inizializzazione dell'app). Quindi è possibile utilizzare questo oggetto per ottenere lo stato corrente con il metodo store.getState() o store.subscribe(listener) per iscriversi agli aggiornamenti del negozio.

Si può anche sicuro questo oggetto per window proprietà di accedervi da qualsiasi parte della domanda, se si vuole veramente (window.store = store)

Maggiori informazioni here

+6

suona un po 'hacky per salvare 'store' nella' finestra' – Vic

+2

@Vic Sure it is :) E normalmente non vuoi farlo. Volevo solo dire che puoi fare tutto ciò che vuoi con questa variabile. Probabilmente l'idea migliore sarebbe salvarla nel file in cui hai creato le vite di "createStore" e quindi importarla da essa. – trashgenerator

15

trovato una soluzione. Quindi importare il negozio nel mio util api e iscriverlo lì. E in quella funzione di ascoltatore ho impostato le impostazioni predefinite globali dell'assios con il mio token appena recuperato.

Questo è ciò che il mio nuovo api.js assomiglia:

// tooling modules 
import axios from 'axios' 

// store 
import store from '../store' 
store.subscribe(listener) 

function select(state) { 
    return state.auth.tokens.authentication_token 
} 

function listener() { 
    let token = select(store.getState()) 
    axios.defaults.headers.common['Authorization'] = token; 
} 

// configuration 
const api = axios.create({ 
    baseURL: 'http://localhost:5001/api/v1', 
    headers: { 
    'Content-Type': 'application/json', 
    } 
}) 

export default api 

Forse può essere ulteriormente migliorata, provocano attualmente sembra un po 'poco elegante. Quello che potrei fare dopo è aggiungere un middleware al mio negozio e impostare il token allora e lì.

+0

puoi condividere come appare il file 'store.js'? – Vic

+0

esattamente qualcosa che stavo cercando, grazie una tonnellata @ rubodh –

69

Esporta lo store dal modulo che hai chiamato createStore con. Quindi sei certo che verrà creato e non inquinerà lo spazio della finestra globale.

MyStore.js

store = createStore(myReducer); export store;

o

store = createStore(myReducer); export default store;

MyClient.js

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

o se è stato utilizzato di default

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

+3

ATTENZIONE per le app isomorfe: facendo questo lato server condivideremo il negozio di redux su tutti i tuoi utenti !!! –

+0

La domanda non chiede come gestire più negozi per più utenti o come gestire lo stato lato server; Semplici domande su come accedere al negozio che è stato definito nel codice specificato. –

+0

Anche la domanda non dichiara esplicitamente "browser". Poiché sia ​​Redux che JavaScript possono essere utilizzati su server o browser, è molto più sicuro essere specifici. –

-1

Per dattiloscritto 2.0 che sarebbe simile a questa:

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(...)} 
+0

Se si sta votando per difetto, si prega di aggiungere un commento perché. – Ogglas

+0

Giù votato perché la tua risposta manca di spiegazione e utilizza TypeScript piuttosto che Javascript. – Will

+0

@Will Grazie per aver detto perché. Imao il codice non richiede specifiche ma se desideri qualcosa di specifico spiegato, per favore dì cosa. TypeScript viene effettivamente utilizzato, ma se vengono rimosse le tipizzazioni lo stesso codice verrà eseguito in ES6 senza problemi. – Ogglas