澳门新浦京娱乐场网站-www.146.net-新浦京娱乐场官网
做最好的网站

自在管理状态,React第三方组件5

React Context API: 轻便管理情况

2018/09/03 · JavaScript · React

初藳出处: Abdulazeez Adeshina   译文出处:OFED   

接受最新的 React Context API 处理状态特别轻便。未来就跟随笔者一齐上学下它和 Redux 的区别以至它是怎么采纳的呢。

**综述:**React Context API 在 React 生态系统中并非个奇特事物。不过,在 React 16.3.0 版本中做了某个改进。这几个改正是这么高大,以至于大大减弱了我们对 Redux 和其他高端状态管理库的需求。在本文中,你将因此三个实用教程理解到新的 React Context API 是哪些代替 Redux 完结Mini应用的景观管理的。


图片 1

Redux 火速回想

在直接奔向主旨以前,大家先来异常快回看下 Redux,以便大家更加好的相比较两个的分化。redux 是一个惠及状态管理的 JavaScript 库。Redux 本人和 React 并不曾提到。来自世界外地的浩大开辟者接收在风行的前端框架(比方 ReactAngular )中使用 Redux。

证实某个,在本文中,状态管理指的是拍卖单页面应用(SPA)中生出的依据特定事件而接触的情景变化。比方,叁个开关的点击事件照旧一条来源于服务器的异步新闻等,都能够接触应用状态的浮动。

在 Redux 中,你更加的供给小心上面几点:

  1. 全体 app 的情事存款和储蓄在单个对象中(该对象被称作数据源)。
  2. 假使要改成状态,你要求通过 dispatch 方法触发 actions,actions 描述了应当产生的事情。
  3. 在 Redux 中,你不能够改动对象的质量或修改现成数组,必得始终再次回到新对象或新数组。

万大器晚成您对 Redux 并不熟习并且你想要掌握愈多,请移步 Redux 的实用教程学习。

title: 翻译|A Dummy’s Guide to Redux and Thunk in React
date: 2017-04-15 21:36:07
categories: 翻译
tags: Redux

图片 2

React Context API 指南

The React Context API 提供了大器晚成种通过组件树传递数据的情势,而毋庸经过 props 属性黄金年代难得的传递。在 React 中,数据日常会作为叁特本性从父组件传递到子组件。

运用新型的 React Context API 须要多少个关键步骤:

  1. 将起来状态传递给 React.createContext。那一个方法会重回八个包蕴 ProviderConsumer 的对象。
  2. 使用 Provider 组件封装在组件树的最外层,并吸收接纳三个 value 属性。value 属性能够是其他值。
  3. 使用 Consumer 组件,在组件树中 Provider 组件内部的另各州方都能博拿到状态的子集。

如您所见,所波及的定义其实与 Redux 未有啥差别。事实上,以致 Redux 也在其公共 API 的底层使用了 React Context API。可是,直到近期,Context API 才到达了十足成熟的水准。


本学科总共6篇,每天更新意气风发篇,请关心我们!你能够步向历史音讯查看以往文章,也敬请期望我们的新作品!

使用 Redux 创建 React 应用

看来,本文的对象是向您来得新的 Context API 如何在迷你应用中代表 Redux。由此,你首先要用 Redux 成立叁个差相当的少的 React app,然后,你将学习如何删除那一个情状处理库,以便越来越好地行使 React Context API。

你将营造的现身说法应用是叁个甩卖局地风靡食品及其来源的列表。这几个动用还将席卷一个追寻作用,使顾客能够基于部分非常重要词过滤列表。

最后,你将创设三个相似下边所述的利用:

Redux和Thunk的施用白痴教程

初稿参见
Github repo
刚烈推荐那篇文章.

假使您和笔者相通,读了Redux的文书档案,看了Dan的雕塑,Wes的科目,仍旧无法抓住怎么利用Redux的主干,希望这几个傻帽事教育程能够帮到你.
在真正实行早前,小编做了某个尝试,所以自身调节写一些从已经存在的接纳fetch JSON数据的app一步步变更为运用Redux和Redux Thunk的app.要是你不通晓Thunk是何等,也毫无操心,大家会在”Redux 之路”部分来行使它推行函数的异步调用.
以此科目须要你对React和ES6/二〇一六有主题的掌握.

1、React第三方组件5(状态管理之Redux的利用①简便利用卡塔尔(英语:State of Qatar)---2018.03.20

种类必要

是因为本文仅使用 React 和部分 NPM 库,因而除了 Node.js 和 NPM 之外,你怎么都不须求。即便你还不曾安装 Node.js 和 NPM,请前往官网下载并安装。

安装那个信任后,你还需求设置 create-react-app 工具。这些工具帮助开垦人士创立 React 项目。张开二个终端并运转以下命令来设置:

npm i -g create-react-app

1
npm i -g create-react-app

非Redux方法

components/ItemList.js中开创二个React组件,用于fetch和突显items列表.

2、React第三方组件5(状态管理之Redux的施用②TodoList上卡塔尔国---2018.03.21

搭建 React 应用

安装完 create-react-app 后,步入项目所在目录,推行以下命令:

create-react-app redux-vs-context

1
create-react-app redux-vs-context

几分钟后,create-react-app 将做到应用程序的创制。在这里之后,步向该工具成立的新目录,并安装 Redux:

# 进入应用目录 cd redux-vs-context # 安装 Redux npm i --save redux react-redux

1
2
3
4
5
# 进入应用目录
cd redux-vs-context
 
# 安装 Redux
npm i --save redux react-redux

注意: redux 是主库,react-redux 是推进 React 和 Redux 之间互相的库。简单来说,前面一个充作 React 和 Redux 之间的代理。

位列一下底蕴零器件

先是大家接受含有种种items的state配置七个静态的机件,2 个boolean state分别用于根据loading和error来渲染出个其他独自展现组件.

 import React, { Component } from 'react';
class ItemList extends Component {
  constructor() {
      super();
      this.state = {
          items: [//items在列表中现实的内容
              {
                  id: 1,
                  label: 'List item 1'
              },
              {
                  id: 2,
                  label: 'List item 2'
              },
              {
                  id: 3,
                  label: 'List item 3'
              },
              {
                  id: 4,
                  label: 'List item 4'
              }
          ],
          hasErrored: false, //网络请求错误的状态
          isLoading: false   //网络请求中的状态
      };
  }
  render() {
      if (this.state.hasErrored) {//根据Errored的状态决
      //定是否加载这个组件,网络请求错误时,false=>true
          return <p>Sorry! There was an error loading the items</p>;
      }
      if (this.state.isLoading) {
      //网络请求中的组件,发出请求时,false=>true
          return <p>Loading…</p>;
      }
      return (
          <ul>
              {this.state.items.map((item) => (
                  <li key={item.id}>
                      {item.label}
                  </li>
              ))}
          </ul>
      );
  }
}
export default ItemList;

莫不看起来还不是专程能证实难题,不过已然是二个好的开端了.
渲染的时候,组件输出四个items列表,但是只要你把isLoadinghasError的state由false改为false的时候,对应的<p></p>就能够呈现出来.(注意每种组件都是return出来的,每一回只呈现二个卡塔尔国.

3、React第三方组件5(状态管理之Redux的运用③TodoList中卡塔尔国---2018.03.22

使用 Redux 开发 React 应用

您曾经搭建好了您的 React 应用,安装好了 Redux,今后,在你欢愉的开采工具中张开你的项目。然后在 src 文件夹中开创八个文件:

  • foods.json :此文件富含叁个用以保存食物及其来源消息的静态数组
  • reducers.js:此文件用于管理应用中 Redux 状态
  • actions.js:此文件用于保存应用中触发 Redux 状态退换的点子

所以,首先,打开 foods.json 文件,增加如下内容:

[ { "name": "Chinese Rice", "origin": "China", "continent": "Asia" }, { "name": "Amala", "origin": "Nigeria", "continent": "Africa" }, { "name": "Banku", "origin": "Ghana", "continent": "Africa" }, { "name": "Pão de Queijo", "origin": "Brazil", "continent": "South America" }, { "name": "Ewa Agoyin", "origin": "Nigeria", "continent": "Africa" } ]

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
[
  {
    "name": "Chinese Rice",
    "origin": "China",
    "continent": "Asia"
  },
  {
    "name": "Amala",
    "origin": "Nigeria",
    "continent": "Africa"
  },
  {
    "name": "Banku",
    "origin": "Ghana",
    "continent": "Africa"
  },
  {
    "name": "Pão de Queijo",
    "origin": "Brazil",
    "continent": "South America"
  },
  {
    "name": "Ewa Agoyin",
    "origin": "Nigeria",
    "continent": "Africa"
  }
]

如你所见,文件存款和储蓄的数码并未有何特别。仅仅是二个暗含着不一致国家分化食品的数组。

在概念了 foods.json 文件后,你能够当心于创建你的 Redux store 了。回想一下,store 是保存你的应用真实境况的唯一来源。张开你的 reducers.js 文件,增多以下代码:

import Food from './foods'; const initialState = { food: Food, searchTerm: '', }; export default function reducer(state = initialState, action) { // 根据 action type 区分 switch (action.type) { case 'SEARCH_INPUT_CHANGED': const {searchTerm} = action.payload; return { ...state, searchTerm: searchTerm, food: searchTerm ? Food.filter( (food) => (food.name.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1) ) : Food, }; default: return state; } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import Food from './foods';
 
const initialState = {
  food: Food,
  searchTerm: '',
};
 
export default function reducer(state = initialState, action) {
  // 根据 action type 区分
  switch (action.type) {
    case 'SEARCH_INPUT_CHANGED':
      const {searchTerm} = action.payload;
      return {
        ...state,
        searchTerm: searchTerm,
        food: searchTerm ? Food.filter(
          (food) => (food.name.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1)
        ) : Food,
      };
    default:
      return state;
  }
}

在地方的代码中,你能够见见 reducer 方法选择多少个参数:stateaction。当您运营你的 React 应用,那几个措施将得到它在此之前定义的 initialState,当您 dispatch 多个 action 的实例时,那几个办法将获取当前气象(不再是 initialState卡塔尔(英语:State of Qatar)。然后,基于那一个actions 的剧情,reducer 方法将为你的使用生成三个新的场地。

接下去,你必要定义那几个 actions 做什么。实际上,为了轻巧起见,你将定义二个纯粹的 action ,当用户在您的采用中输入搜索词时,那几个 action 会被触发。由此,张开 actions.js 文件,并在内部插入以下代码:

function searchTermChanged(searchTerm) { return { type: 'SEARCH_INPUT_CHANGED', payload: {searchTerm}, }; } export default { searchTermChanged, };

1
2
3
4
5
6
7
8
9
10
function searchTermChanged(searchTerm) {
  return {
    type: 'SEARCH_INPUT_CHANGED',
    payload: {searchTerm},
  };
}
 
export default {
  searchTermChanged,
};

action 创造好之后,你要求做的下黄金年代件事就是将你的 App 组件封装到 react-redux 提供的 Provider 组件中。Provider 统大器晚成担负 React 应用的数目(即 store)传递。

要动用 provider ,首先,你将动用 reducers.js 中定义的 initialState 创建 store。然后,通过 Provider 组件,你将把 store 传给你的 App。要做到那几个职务,你必须要展开 index.js 文件,并将其内容替换为:

import React from 'react'; import ReactDOM from 'react-dom'; import {Provider} from 'react-redux'; import {createStore} from 'redux'; import reducers from './reducers'; import App from './App'; // 使用 reducers 消息创造 store。 // 那是因为 reducers 是 Redux Store 的主宰中央。 const store = createStore(reducers卡塔尔; ReactDOM.render( <Provider store={store}> <App/> </Provider>, document.getElementById('root'卡塔尔国 卡塔尔(قطر‎;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from 'react-redux';
import {createStore} from 'redux';
import reducers from './reducers';
import App from './App';
 
// 使用 reducers 信息创建 store。
// 这是因为 reducers 是 Redux Store 的控制中心。
const store = createStore(reducers);
 
ReactDOM.render(
  <Provider store={store}>
    <App/>
  </Provider>,
  document.getElementById('root')
);

正是这么!你刚好在 React 应用中结构完 Redux。未来,你不得不兑现 UI (客商分界面卡塔尔(英语:State of Qatar),那样您的顾客就可以运用本节中落到实处的职能了。

改为动态值

直白编码items对于组件来讲不是专门有用,所以最佳从JSON API来fetch items多少,假如那样做的话,大家就足以把isLoadinghasError改为适当的状态.
响应值和大家直接编码是雷同,然则在实际分娩中,你也许会拉回叁个图书抢手榜的列表,最新的blog帖子大概其余app中供给的内容.
为了fetch items,我们将应用优秀的Fetch API.Fetch使得执行伏乞比守旧的XMLHttpRequest更易于,而且再次来到的是响应值的promise对象(这或多或少对此Thunk很关键卡塔尔(英语:State of Qatar).Fetch并非在享有的浏览器中都能够应用,所以您须要在项目中加上信赖项.

 npm install whatwg-fetch --save

变迁实际上格外轻松.

  • 首先把items的开首化state设置为空数组
  • 如今大家增加八个方式fetch数据,同期还要设定loading和error的状态.
fetchData(url) {//fetch的包装方法
  //进入函数首先设定isLoading state false=>true
  this.setState({ isLoading: true });
  fetch(url)
      .then((response) => {//返回promise独享
          if (!response.ok) {
              throw Error(response.statusText);
          }
          //不管返回的数据是什么,只要返回数据
          //就修改isLoading state true=>false
          this.setState({ isLoading: false });
          return response;
      })
      .then((response) => response.json())
      .then((items) => this.setState({ items })) 
      // ES6 property value shorthand for { items: items }
      .catch(() => this.setState({ hasErrored: true }));//返回数据的解析为json,如果捕获到错误就hasErrored:
      // false=>true
}
  • 函数写完事后,在组件加载的时候就调用函数
 componentDidMount() {
 this.fetchData('http://      5826ed963900d612000138bd.mockapi.io/items');
}

完毕之后,代码如下

 class ItemList extends Component {
   constructor() {
       this.state = {
           items: [],
       };
   }
   fetchData(url) {
       this.setState({ isLoading: true });
       fetch(url)
           .then((response) => {
               if (!response.ok) {
                   throw Error(response.statusText);
               }
               this.setState({ isLoading: false });
               return response;
           })
           .then((response) => response.json())
           .then((items) => this.setState({ items }))
           .catch(() => this.setState({ hasErrored: true }));
   }
   componentDidMount() {
       this.fetchData('http://5826ed963900d612000138bd.mockapi.io/items');
   }
   render() {
   }
}

差不离了,组件以后从REST API fetch items数据,在4个items达到早先,你希望看”Loading...”现身提醒.假设U福睿斯L不能够回来数据,你应当见到error 的音讯.

唯独(译注:讨厌的不过卡塔尔(英语:State of Qatar),在实际中,组件不该包蕴具体的fetch逻辑,data也不该储存在组件的state中,所以Redux实时的面世了.

4、React第三方组件5(状态管理之Redux的施用④TodoList下卡塔尔---2018.03.23

创建 React 界面

现行反革命,你已经产生了利用中的大旨代码,你能够小心于构建你的客户分界面。为此,张开你的 App.js 文件,用下方代码替换它的剧情:

import React from 'react'; import {connect} from 'react-redux'; import actions from './actions'; import './App.css'; function App({food, searchTerm, searchTermChanged}) { return ( <div> <div className="search"> <input type="text" name="search" placeholder="Search" value={searchTerm} onChange={e => searchTermChanged(e.target.value)} /> </div> <table> <thead> <tr> <th>Name</th> <th>Origin</th> <th>Continent</th> </tr> </thead> <tbody> {food.map(theFood => ( <tr key={theFood.name}> <td>{theFood.name}</td> <td>{theFood.origin}</td> <td>{theFood.continent}</td> </tr> ))} </tbody> </table> </div> ); } export default connect(store => store, actions)(App);

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
29
30
31
32
33
34
35
36
37
38
39
40
import React from 'react';
import {connect} from 'react-redux';
import actions from './actions';
import './App.css';
 
function App({food, searchTerm, searchTermChanged}) {
  return (
    <div>
      <div className="search">
        <input
          type="text"
          name="search"
          placeholder="Search"
          value={searchTerm}
          onChange={e => searchTermChanged(e.target.value)}
        />
      </div>
      <table>
        <thead>
        <tr>
          <th>Name</th>
          <th>Origin</th>
          <th>Continent</th>
        </tr>
        </thead>
        <tbody>
        {food.map(theFood => (
          <tr key={theFood.name}>
            <td>{theFood.name}</td>
            <td>{theFood.origin}</td>
            <td>{theFood.continent}</td>
          </tr>
        ))}
        </tbody>
      </table>
    </div>
  );
}
 
export default connect(store => store, actions)(App);

对于未用过 Redux 的人来讲,他们独一不熟练的是用以封装 App 组件的 connect 方法。那一个主意其实是多少个高阶组件( HOC 卡塔尔国,当做应用程序和 Redux 之间的粘结剂。

运用以下命令运维你的施用,你将能够在浏览器中拜会你的行使:

npm run start

1
npm run start

而是,正如您所观察的,那么些应用今后很无耻。由此,为了让它看起来越来越好一些,你能够张开 App.css 文件,用以下内容替换它的原委:

table { width: 100%; border-collapse: collapse; margin-top: 15px; line-height: 25px; } th { background-color: #eee; } td, th { text-align: center; } td:first-child { text-align: left; } input { min-width: 300px; border: 1px solid #999; border-radius: 2px; line-height: 25px; }

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
table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 15px;
  line-height: 25px;
}
 
th {
  background-color: #eee;
}
 
td, th {
  text-align: center;
}
 
td:first-child {
  text-align: left;
}
 
input {
  min-width: 300px;
  border: 1px solid #999;
  border-radius: 2px;
  line-height: 25px;
}

图片 3

完了了!你以后有了一个基本的 React 和 Redux 的采纳,能够起来学习怎么样迁移到 Context API 上了。

转变到Redux

内需增加Redux, React Redux 和Redux Thunk作为依附项.

 npm install redux react-redux redux-thunk --save

5、React第三方组件5(状态管理之Redux的接纳⑤异步操作卡塔尔---2018.03.26

行使 React Context API 完成接收

在本节,你将要学习怎么将您的 Redux 应用迁移到 React Context API 上。

有幸的是,你不要求在 Redux 和 Context API 之间做过多的重构。

首先,你不得不从您的应用中移除 Redux 组件。为此,请打开终端,删除 reduxreact-redux 库:

npm rm redux react-redux

1
npm rm redux react-redux

其后,删除应用中对这几个库的引用代码。打开 App.js 删除以下几行:

import {connect} from 'react-redux'; import actions from './actions';

1
2
import {connect} from 'react-redux';
import actions from './actions';

然后,在一直以来的公文中,用下方的代码替换最终少年老成行(以 export default 开首的那少年老成行):

export default App;

1
export default App;

通过这几个改动,你能够用 Context API 重写你的利用了。

理解Redux

有多少个Redux的中坚原理,大家亟需求驾驭(译注:话极粗略,不过要在大脑里营造出Redux的工作流程是有花超级多岁月的和活力的卡塔尔国.

  1. Redux中有贰个大局state对象来保管整个应用的state.在篇作品中,全局对象就是我们组件的最早化对象.
  2. 唯风流倜傥能更正state的是触发一个action,action是二个陈述state应该怎么转移的对象,Action Creators能够被dispatched的函数,触发二个变迁,试行的开始和结果是回来三个action
  3. 当多少个action被dispatch今后,Reducer实践遵照action的内容实在更换state对象,假使action未有找到相称项,就会回去暗中认可的state.
  4. Reducers是纯函数,他们不能有任何的异步操作和mutate-必须要返回一个修改的copy.
  5. 单个的Reducer能够被combine为叁个单意气风发的rootReducer,进而开创二个离散的state聚合体.
  6. Store是把action和reducer组织到黄金年代道的工具,他包罗了rootReducer意味着的情状,中间件,允许你执行实际的dispatchactions
  7. 为了在React中使用Redux,<Provider />零件封装整个应用,传递store到子代组件们.

6、React第三方组件5(状态管理之Redux的接纳⑥Redux DevTools卡塔尔(قطر‎---2018.03.27

从 Redux 迁移到 React Context API

要将事前的使用从 Redux 驱动的使用转变为使用 Context API,你须要叁个context 来囤积应用的数据(该 context 将替换 Redux Store卡塔尔(قطر‎。别的,你还要求一个 Context.Provider 组件,该器件包蕴 stateprops 和寻常的 React 组件生命周期。

为此,你必要在 src 目录中开创叁个 providers.js 文件,并向里面加多以下代码:

import React from 'react'; import Food from './foods'; const DEFAULT_STATE = { allFood: Food, searchTerm: '' }; export const ThemeContext = React.createContext(DEFAULT_STATE); export default class Provider extends React.Component { state = DEFAULT_STATE; searchTermChanged = searchTerm => { this.setState({searchTerm}); }; render() { return ( <ThemeContext.Provider value={{ ...this.state, searchTermChanged: this.searchTermChanged, }}> {this.props.children} </ThemeContext.Provider>); } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import React from 'react';
import Food from './foods';
 
const DEFAULT_STATE = { allFood: Food, searchTerm: '' };
 
export const ThemeContext = React.createContext(DEFAULT_STATE);
 
export default class Provider extends React.Component {
  state = DEFAULT_STATE;
  searchTermChanged = searchTerm => {
    this.setState({searchTerm});
  };
 
  render() {
    return (
      <ThemeContext.Provider value={{
        ...this.state,
        searchTermChanged: this.searchTermChanged,
      }}> {this.props.children} </ThemeContext.Provider>);
  }
}

地点代码中定义的 Provider 类肩负将其余零器件封装在 ThemeContext.Provider 中。通过如此做,你能够让这几个零部件访问应用中的 state 和改动 state 的 searchTermChanged 方法。

若要在组件树中选拔这个值,你要求成立五个 ThemeContext.Consumer 组件。那一个组件将索要五个 render 渲染方法,该方法将选取上述 props 值作为参数。

为此,接下去,你须求在 src 目录中开创三个名字为 consumer.js 的文书,并将以下代码写入此中:

import React from 'react'; import {ThemeContext} from './providers'; export default class Consumer extends React.Component { render() { const {children} = this.props; return ( <ThemeContext.Consumer> {({allFood, searchTerm, searchTermChanged}) => { const food = searchTerm ? allFood.filter( food => food.name.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1 ) : allFood; return React.Children.map(children, child => React.cloneElement(child, { food, searchTerm, searchTermChanged, }) ); }} </ThemeContext.Consumer> ); } }

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
29
import React from 'react';
import {ThemeContext} from './providers';
 
export default class Consumer extends React.Component {
  render() {
    const {children} = this.props;
 
    return (
      <ThemeContext.Consumer>
        {({allFood, searchTerm, searchTermChanged}) => {
          const food = searchTerm
            ? allFood.filter(
              food =>
                food.name.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1
            )
            : allFood;
 
          return React.Children.map(children, child =>
            React.cloneElement(child, {
              food,
              searchTerm,
              searchTermChanged,
            })
          );
        }}
      </ThemeContext.Consumer>
    );
  }
}

当今,为了完结搬迁,你将开垦 index.js 文件,并在 render() 函数中,用 Consumer 组件封装 App 组件。别的,你需求将 Consumer 包装在 Provider 组件中。代码如下所示:

import React from 'react'; import ReactDOM from 'react-dom'; import Provider from './providers'; import Consumer from './consumer'; import App from './App'; ReactDOM.render( <Provider> <Consumer> <App /> </Consumer> </Provider>, document.getElementById('root') );

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import React from 'react';
import ReactDOM from 'react-dom';
import Provider from './providers';
import Consumer from './consumer';
import App from './App';
 
ReactDOM.render(
  <Provider>
    <Consumer>
      <App />
    </Consumer>
  </Provider>,
  document.getElementById('root')
);

打完收工!你刚刚产生了从 Redux 到 React Context API 的迁移。要是你以往起首你的运用,你会开采任何应用运维不奇怪化。独一分化的是,你的采纳不再行使 Redux 了。

“新增加的 React Context API 在裁减应用容量方面是 Redux 的佳绩代替品。”

两全大家的state

从我们前几天已有些代码里,能够了然我们的state需求3个特性(properties卡塔尔国:items,hasErrored,isLoading,这一个多少个属性相应的内需三个独立的actions.

近来,这里讲讲怎么Action Creator和Action是例外的,他们亦非1:1的涉及:大家须求第七个actiong creator来依据fetch data的不等意况调用别的多少个action(creators卡塔尔(قطر‎.这第多少个action creator差不离和我们原先的fetchData()平等,不过它不会平素的选取this.setState({isLoading:true})来设置景况,大家将dispatch二个action去做相似的业务:dispatch(isLoading(true)).

付出景况:Windows 8,node v8.9.1,npm 5.5.1,WebStorm 2017.2.2

题外话:使用 Auth0 使您的 React 应用更安全

初藳中有关于 Auth0 使用的详实教程,但译者以为这里内容和本文主旨关系超级小,故不作翻译。感兴趣者可活动原文开卷该片段内容。

创建actions

在actions目录下创设itmes.js文件,此中含有我们的action creators.创设七个轻巧的actions.

    export function itemsHasErrored(bool) {
   return {
       type: 'ITEMS_HAS_ERRORED',
       hasErrored: bool
   };
}
export function itemsIsLoading(bool) {
   return {
       type: 'ITEMS_IS_LOADING',
       isLoading: bool
   };
}
export function itemsFetchDataSuccess(items) {
   return {
       type: 'ITEMS_FETCH_DATA_SUCCESS',
       items
   };
}


    ```











如前面提到的,action creators似能返回函数的函数,使用`export`输出单个action creators,便于在代码中使用.
   第二个action creators接受一个布尔值(true/false)最为参数,返回一个有意义的`type`和布尔值,分配合适的属性.
   第三个,`itemsFetchSuccess()`,当数据成功返回以后,传递数据作为`items`属性的值.通过ES6的魔术属性缩写,我们能够返回一个对象含有属性名叫做`items`,他的值是`items`的数组.

  (Note: that the value you use for type and the name of the other property that is returned is important, because you will re-use them in your reducers)这一句不知道怎么翻译.
  现在,我们有了三个actions,代表我们的状态,把原来的组件方法`fetchData`该给`itemFetchDaga()`action creator.
  默认情况下,Redux action creators是不支持异步actions的,像是fetching data的操作,所以这里我们使用Redux Thunk.Thunk允许你在action creator里返回一个函数代替实际的action.内部函数接受`dispatch`和`getState`作为参数,但是我们仅仅使用`dispatch`.
  实际的简单例子中五秒以后将会触发`itemHasErrored()`函数.


export function errorAfterFiveSeconds() {
// We return a function instead of an action object
//dispatch作为参数传递给胖箭头函数
return (dispatch) => {
    setTimeout(() => {
        // This function is able to dispatch other action creators
        dispatch(itemsHasErrored(true));
    }, 5000);
};

}

现在我们知道thunk是什么了.编写`itemsFetchData()`.

export function itemsFetchData(url) {
return (dispatch) => {
    //已进入fetchdata,按顺序把isLoading state 由
    // false=>true
    dispatch(itemsIsLoading(true));
    //fetch执行实际的异步远程获取数据操作
    fetch(url) 
        .then((response) => {
            if (!response.ok) {//根据状态抛出错误
                throw Error(response.statusText);
            }
            //isLoading又改为false,加载Loading组件
            dispatch(itemsIsLoading(false));
            return response;
        })
        .then((response) => response.json())
        .then((items) => dispatch(itemsFetchDataSuccess(items)))
        .catch(() => 
        dispatch(itemsHasErrored(true)));
        //捕获错误以后HasError的状态 false=>true
};

}

## 创建我们的reducers

action定义好了以后,可以编写reducers接受actions,接着返回appliction的新状态(译注:实际上store中返回的对象都是一个新的对象,不是原对象的引用,这个就叫做immutable,facebook定义了一个immutable.js的技术实际是也是返回一个新的对象的硬拷贝,但是在原对象和修改对象之间共享了一部分内容,这一点有点微妙).
注意:在Redux中,所有的reducers不考虑action,都会调用,所以即就是没有action被应用,你也必须要返回一个原来的定义的`state`.

每一个reducer接收两个参数,之前的state和一个`action`对象.也可以使用ES6的属性来调用默认的参数设定到默认的`初始化state`.

在每个reducer内部,使用`switch`申明来决定到底哪个`action.type`相匹配.如果是简单的reducer,可能没有必要使用`switch`,理论上使用`if/else`可能更快一点.

如果`action.type`一点匹配,然后会返回和`action`相关的属性.和前面提到的一样,`type`和`action[属性名]`是在action creators里定义的.

好啦,了解到这些内容,在`reducers/item.js`中创建items reducers

export function itemsHasErrored(state = false, action) {
switch (action.type) {
case 'ITEMS_HAS_ERRORED':
return action.hasErrored;
default:
return state;
}
}
export function itemsIsLoading(state = false, action) {
switch (action.type) {
case 'ITEMS_IS_LOADING':
return action.isLoading;
default:
return state;
}
}
export function items(state = [], action) {
switch (action.type) {
case 'ITEMS_FETCH_DATA_SUCCESS':
return action.items;
default:
return state;
}
}

注意reducer根据结果store的state属性来命名,`action.type`没有必要想对应.前两个表达完整的意思,第三个`items()`就稍微有点不同.

这是因为,可能会有很多条件返回`items`数组:有可能返回所有的数组,有可能在删除dispatch以后返回`items`的次级结构.或者所有的items都被删除了,会返回一个空数组.

为了重新遍历,每一个reducer都会返回一个截然不同的state属性,不需要考虑reducer内部的条件到底有多少.刚开始花了我很长时间想明白这个问题.
单个的reducers创建好了以后,我们需要把单个的reducer合并(combine)成一个`rootReducer`,创建单一对象.

创建文件`reducers/index.js`

import { combineReducers } from 'redux';
import { items, itemsHasErrored, itemsIsLoading } from './items';
//由于各种reducer再次来到的都以一个对象
//所以这里的操作正是统豆蔻梢头对象的操作,在underscore和loadsh
//里面能够找到归拢js对象的代码
export default combineReducers({
items,
itemsHasErrored,
itemsIsLoading
});

我们从`items`里导入每个reducers,使用redux的`combineReducers()`函数来合并输出单一对象(译注:所以每一个reducer返回的对象的属性名应该是唯一的,否则就覆盖了,前面的内容表达过这个意思)
因为我们的reducer的名字和在store中使用的属性名一样,所以我们可以使用ES6的对象字面量.

注意,我有意提到了reducer的前缀,所以当我们的application变得比较复杂的时候,不能出现全局性的`hasErrored`和`isLoading`属性.可以使用不同的error和loading state,所以前缀可以给你很大的灵活性.例如

import { combineReducers } from 'redux';

import { items, itemsHasErrored, itemsIsLoading } from './items';
import { posts, postsHasErrored, postsIsLoading } from './posts';
export default combineReducers({
items,
itemsHasErrored,
itemsIsLoading,
posts,
postsHasErrored,
postsIsLoading
});

替代方法是,可以在import的时候使用别名.但是我更愿意使用独一无二的名字.

## 配置store,注入到你的app中

操作很直接,创建`store/configureStore.js`

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from '../reducers';
export default function configureStore(initialState) {
return createStore(
rootReducer,
initialState,
applyMiddleware(thunk)
);
}

现在在index.js中包含`<Provider />`组件,`configureStore`,配置`store`.包装app(`<ItemList />`),传递进去`store`和`props`.

import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import configureStore from './store/configureStore';
import ItemList from './components/ItemList';
const store = configureStore(); // You can also pass in an initialState here
render(
<Provider store={store}>
<ItemList />
</Provider>,
document.getElementById('app')
);

我知道,其实花了很多努力才到了这一步,但是随着设置的完成,我们就可以使用配置来操纵我们的组件了(译注:这里是意译,组件又称为木偶组件,意思很清楚吧?谁是拿着吊线的人呢?就是redux).

## 把组件转化为使用Redux store和方法

跳回到`components/ItemList.js`

在顶部导入需要的部分

import { connect } from 'react-redux';
自在管理状态,React第三方组件5。import { itemsFetchData } from '../actions/items';

`connect`可以让组件链接到Redux的store,`itemsFetchData`是在开始写的action creator.我们仅仅需要导入actin creator.使用`dispatch`来触发actions.(译注:redux里面有很多内容其实是很基础的,例如这里,javascript的函数是一类对象,在js中函数是传引用的,所以函数名可以作为函数的引用,通过另一函数的参数来传递. 厉害 
		

本文由澳门新浦京娱乐场网站发布于新浦京娱乐场官网,转载请注明出处:自在管理状态,React第三方组件5