react怎么在其他文件里获取store变量

JavaScript012

react怎么在其他文件里获取store变量,第1张

方法一:导出 store

这应该是最简单省事同时也容易想到的方法,但是有一点需要注意:

不要在服务端渲染中使用该方法

如果你在使用服务端渲染的 app 中直接导出 store,那么 app 的所有 user 都会获得一个单例的 store (包括相同的 JWT Token),这肯定不是你乐见的。

除去上述这种情况,当我们需要获取 store 中的 JWT Token 时,可以这么做:

/*

store.js

*/

import { createStore } from 'redux'

import reducer from './reducer'

const store = createStore(reducer)

export default store

1

2

3

4

5

6

7

8

9

1

2

3

4

5

6

7

8

9

创建 store 的方法还和以前一样,仅仅是导出它,以便于在其他文件中使用。

不要担心你使用的 createStore 方法可能会很复杂,放心的使用各种中间件比如 thunk, saga, devtools ,你需要做的仅仅是导出 store 而已。

紧接着,在需要用到 store 中数据的地方,引入 (import) 它。下面的例子就是我们在一个普通函数 api.js 中将 store 中的 JWT Token 通过 ajax 传递给服务端。

/**

api.js

**/

import store from './store'

export function getProtectedThing() {

// grab current state

const state = store.getState()

// get the JWT token out of it

// (obviously depends on how your store is structured)

const authToken = state.currentUser.token

// Pass the token to the server

return fetch('/user/thing', {

method: 'GET',

headers: {

Authorization: `Bearer ${authToken}`

}

}).then(res =>res.json())

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

在 Redux 官网的 FAQ 中有这样一个问题 我可以在组件中直接引入 store 并使用吗 ?

其实如果需要在 React 组件中使用 store,我们有更好的选择 (译者注:也是官方提倡的):那就是使用 React-Redux 中的 connect 方法。

Mark Erikson,Redux 的维护者之一,在 Reddit 上就这个问题发表过如下看法:

通常情况下,不建议在 component 中通过 import 的方式来使用 store.

在某些情况下,可以试着通过 thunk 或者其他一些 Redux 中间件来操作 store 而不是直接去引用它。

但是凡事总有例外,打我自己的比方,有一个项目中 70% 的代码使用 Backbone 写的,在项目的一些模块中,我们同时需要来自 Backbone models 和 Redux store 中的数据,在这部分模块中,我们的确需要 import {store} from “store” 这种直接的引用方式,因为我们的确没有其他选择。

所以,直接引用并不是理想的方式,但是,如果有必要,也可以。

React Component 之外 dispatch action

如果你在 React Component 之外需要 dispatch action,那么同样的方法也是适用的:引入 store 然后再调用 store.dispatch(),这和你在 react-redux 中通过 connect 函数获取到 dispatch 是一样的。

方法二:从 thunk 中获取 redux 的 state

如果你需要在 thunk 中获取 redux store 中的某项数据,更简单不过。你根本不需要直接引入 store,因为 thunk 的 action 中有一个 getState 的输入参数。

下面的例子就是从 thunk 的 action 创建函数中获取 JWT Token.

/** actions.js **/

export function getProtectedThing() {

return (dispatch, getState) =>{

// grab current state

const state = getState()

// get the JWT token out of it

// (obviously depends on how your store is structured)

const authToken = state.currentUser.token

// Pass the token to the server

return fetch('/user/thing', {

method: 'GET',

headers: {

Authorization: `Bearer ${authToken}`

}

}).then(res =>res.json())

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

另外,如果你不想在 thunk 的 action 函数中直接使用 fetch,你可以选择将 fetch 封装到另外一个类中比如 api.js. 当然你需要额外的参数将所需数据传递出去。

方法三:使用中间件(middleware)截获 action 中的数据

如果你不喜欢上述两种方法 (或是无法使用),那么也可以试试下面这种方法。

开发一个自定义的 redux 中间件,“拦截” 特定的 action. 在 action 触达 store 之前获取其携带的数据,甚至在中间件中直接获取 store.

我们还以 JWT Token 为例。假设应用程序在用户成功登陆后会触发一个 LOG_SUCCESS 的 action,该 action 携带的数据包含 JWT Token.

/*

index.js

*/

const saveAuthToken = store =>next =>action =>{

if(action.type === 'LOGIN_SUCCESS') {

// after a successful login, update the token in the API

api.setToken(action.payload.authToken)

}

// continue processing this action

return next(action)

}

const store = createStore(

reducer,

applyMiddleware(saveAuthToken)

)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

在你的 api.js 中会有一个 setToken 的方法将 token 赋值给本地变量。

/*

api.js

*/

let currentAuthToken = null

export function setToken(token) {

currentAuthToken = token

}

export function getProtectedThing() {

// Pass the token to the server

return fetch('/user/thing', {

method: 'GET',

headers: {

Authorization: `Bearer ${currentAuthToken}`

}

}).then(res =>res.json())

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

如果你使用的 http 库是 axios, 你在 setToken 中可以直接将 token 赋值到 axios 实例的 Authorization header,axios 在发送请求时请求头会自动包含该字段。

import axios from 'axios'

export function setToken(token) {

axios.defaults.headers.common['Authorization'] =

`Bearer ${token}`

}

1

2

3

4

5

6

1

2

3

4

5

6

方法四:在 React 组件中传值

(译者注:这种方法和主题无关了,就是组件内通过 connect 的方式)

import React from 'react'

import { connect } from 'react-redux'

import * as api from 'api'

const ItemList = ({ authToken, items }) =>{

return (

<ul>

{items.map(item =>(

<li key={item.id}>

{item.name}

<button

onClick={

() =>api.deleteItem(item, authToken)

}>

DELETE THIS ITEM

</button>

</li>

)}

</ul>

)

}

const mapStateToProps = state =>({

authToken: state.currentUser &&state.currentUser.authToken,

items: state.items

})

export connect(mapStateToProps)(ItemList)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

状态管理有5个核心,分别是state、mutation、getter、action、module

(1)state

简单的理解,可以把state想象成组件中的data,专门用来存储数据的。

如果在组件中,想要访问store中的数据,只能通过```this.$store.state.xxx来访问

(2)mutation

负责修改state中的数据

如果要操作store中的state值,不推荐直接操作state中的数据,推荐通过调用mutations提供的方法来操作对应的数据。mutation的作用如下图:

(4)action

action和mutation有些类似,不同在于

(5)mudule

module解决了当state复杂臃肿的时候,module可以将store分割成模块,每个模块拥有直接的state、mutation、action和getter。