成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

react new context API的一次實踐(補充)

kaka / 2916人閱讀

摘要:作為數(shù)據(jù)的發(fā)布方,它擁有一個名為的屬性,用于維護數(shù)據(jù)內(nèi)容,通過傳遞給的數(shù)據(jù)會被發(fā)布出去。最后,組件將自己的原封不動的傳遞給。但是通過這次的實踐,也算是熟悉的的用法,對也加深了了解吧。

這是一篇我發(fā)在掘金上的文章,原文有一個我沒有解決的問題,在網(wǎng)友的解答下我找到了答案,我把文章重新修改編輯后,同步發(fā)送到這里,希望能對大家有所幫助。
本文原發(fā)布于掘金:https://juejin.im/post/5a900d...

最近接到一個簡單的內(nèi)部項目,邏輯并不復(fù)雜,就想著不用redux了,用react的new context API試試看,折騰了兩天,把過程和感想跟大家分享下。

由于是公司的項目,所以下文的示例代碼都是我重新寫的,望見諒!

基本用法

首先,讓我們來看一下這個接口的基本用法:
使用它首先需要使用react的createContext方法創(chuàng)建一個實例:

import React, { createContext } from "react";
const Context = createContext({
  gender: "male"
});;

Context實例提供兩個組件:Provider和Consumer

const ContextProvider = Context.Provider;
const ContextConsumer = Context.Consumer;

其中ContextProvider是數(shù)據(jù)的發(fā)布方,而ContextConsumer是數(shù)據(jù)的訂閱方。


    
        {
            context => (
                
name:  {context.name}  age:  {context.age}
) }

ContextProvider作為數(shù)據(jù)的發(fā)布方,它擁有一個名為value的屬性,用于維護數(shù)據(jù)內(nèi)容,通過value傳遞給ContextProvider的數(shù)據(jù)會被發(fā)布出去。
而ContextConsumer作為數(shù)據(jù)的訂閱方,它的props.children是一個函數(shù),接收的參數(shù)是被發(fā)布的數(shù)據(jù),我們通過調(diào)用這個函數(shù)來獲取被ContextProvider發(fā)布的數(shù)據(jù),并且返回我們想要渲染的組件。
在這個示例中,我們最后在頁面上能夠顯示出name: A age: 18。

關(guān)于調(diào)用createContext方法時候的傳參,理論上第一個傳參應(yīng)該是初始化的數(shù)據(jù),但是我使用后發(fā)現(xiàn),如果在ContextProvider的value屬性中不傳入對應(yīng)的屬性的話,無法在ContextConsumer中獲取到那個初始化的屬性。

const Context = createContext({ gender: "male" });

    
        {
            context => (
                
name:  {context.name}  age:  {context.age}
) }

這個例子中,我始終無法獲取到gender的值。
我目前還沒找到原因,如果知道的朋友請告訴我一下,謝謝!

補充

經(jīng)過網(wǎng)友的解答和我自己的試驗,這個問題得到了解答:

Provider的value屬性會把初始化Context時傳遞的初始狀態(tài)給覆蓋掉;

如果想要使用初始的狀態(tài),那么就不能使用Provider,也就是說,只有訂閱數(shù)據(jù)而不發(fā)布新數(shù)據(jù)的情況下,初始的狀態(tài)才會有效;

實踐

為了適應(yīng)項目的需求,我主要是對ContextProvider和ContextConsumer做了封裝。

ContextProvider

由于在我的項目中組件需要訂閱并且修改和維護被發(fā)布的數(shù)據(jù),所以我需要有一個可以維護這些數(shù)據(jù)的地方。因此我創(chuàng)建了一個名為MyProvider的高階組件,并把它放在組件樹的頂層,而各個組件需要訂閱的數(shù)據(jù)就存放在MyProvider的state中,那么我只需要維護它的state就能維護這些全局的數(shù)據(jù)了。

export class MyProvider extends React.Component {
  constructor() {
    super();
    this.state = {
      name: "A",
      age: 18
    };
    this.updateContext = this.updateContext.bind(this);
  }
  updateContext(newData) {
    this.setState(Object.assign({}, this.state, newData));
  }
  render() {
    const contextData = { data: this.state };
    Object.defineProperty(contextData, "updateContext", {
      value: this.updateContext
    });
    return (
      
        {this.props.children}
      
    );
  }
}

MyProvider組件返回的是ContextProvider組件,并把MyProvider的state作為要發(fā)布的數(shù)據(jù)綁定到了ContextProvider的value屬性上。
前面講過,由于其他組件有要修改被發(fā)布數(shù)據(jù)的需求,所以我給數(shù)據(jù)添加了一個不可修改的方法updateContext,這個方法能夠接收新的數(shù)據(jù)并更新MyProvider的state,即更新了被發(fā)布的數(shù)據(jù)。
最后,MyProvider組件將自己的children原封不動的傳遞給ContextProvider。

ContextConsumer

考慮到ContextConsumer作為訂閱方使用比較頻繁,為了方便其他組件的使用,我將它封裝到高階組件中,并作為函數(shù)的返回值使用,如下:

export const MyConsumer = Component => {
  return props => (
    
      {context => {
        return ;
      }}
    
  );
};

MyConsumer函數(shù)返回一個高階組件。在這個高階組件中,我把ContextConsumer提供的數(shù)據(jù)加入到Component的props中,這樣我只需要在export組件的時候調(diào)用MyConsumer,并且在組件中使用this.props.context.data就能得到被發(fā)布的數(shù)據(jù)了。如下:

class MyComponent extends React.Component {
  addAge() {
    const { data: { age }, updateContext } = this.props.context;
    const newAge = age + 1;
    updateContext({ age: newAge });
  }
  render() {
    const { name, age } = this.props.context.data;
    return (
      
name: {name} age: {age}
); } } export default Consumer(MyComponent);

在這個例子中,點擊按鈕,調(diào)用this.props.context.updateContext方法就可以通過更新MyProvider的state來修改被發(fā)布數(shù)據(jù)中的age的值。

示例代碼:react-new-context-api-demo

小結(jié)

我折騰了兩天之后才反應(yīng)過來,這不就是一個類似于redux的東西嗎?
可能由于我redux用的多了,對于Prvider和Consumer的封裝下意識的做成了類似redux的用法。再加上使用MyProvider的state作為唯一數(shù)據(jù)源,又有updateContext這個有點像dispatch的方法來更新數(shù)據(jù),乍一看之下,還是有點redux的影子的。
當(dāng)然了,我自己寫的完全沒有redux那么好用,也沒有reudx那么嚴謹。所以,后來我又花了一個上午的時間改用了redux。
但是通過這次的實踐,也算是熟悉的new context api的用法,對redux也加深了了解吧。
最后,如果你只是想要訂閱數(shù)據(jù),new context api是個不錯的選擇;但是如果你想要修改和維護被發(fā)布的數(shù)據(jù),使用redux會更方便和安全。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/95115.html

相關(guān)文章

  • Why React?

    摘要:觀察者模式,一次創(chuàng)建多條通信鏈路,每條鏈路工作時與其他鏈路發(fā)生干擾。在目前系統(tǒng)中,只存在兄弟通信和父子通信,不存在跨樹通信,即孩子不能跟叔叔直接通信。模擬操作的方式,歸根到底是把手動測試過程用腳本記錄下來。 作者:BrianLi (部門同事李老師,口頭授權(quán)發(fā)布內(nèi)部react布道資料) 無法用語言準確表達思維時,就用公式;一個不行,那就兩個 —— 李老師 本文假設(shè)讀者已了解react的基...

    JayChen 評論0 收藏0
  • 對服務(wù)端渲染一次實踐(帶你掌握服務(wù)端渲染)

    摘要:之前做的一個應(yīng)用,最近把首頁改成了服務(wù)端渲染的形式,過程還是很周折的,踩到了不少坑,記錄一些重點,希望有所幫助前端使用的技術(shù)棧升級到升級到服務(wù)項目地址喜歡的給個,感謝。。。。。。。 之前react做的一個應(yīng)用,最近把首頁改成了服務(wù)端渲染的形式,過程還是很周折的,踩到了不少坑,記錄一些重點,希望有所幫助 前端使用的技術(shù)棧 react、react-dom 升級到 v16 react-ro...

    v1 評論0 收藏0
  • 如何優(yōu)化你的超大型React應(yīng)用 【原創(chuàng)精讀】

    摘要:往往純的單頁面應(yīng)用一般不會太復(fù)雜,所以這里不引入和等等,在后面復(fù)雜的跨平臺應(yīng)用中我會將那些技術(shù)一擁而上。構(gòu)建極度復(fù)雜,超大數(shù)據(jù)的應(yīng)用。 showImg(https://segmentfault.com/img/bVbvphv?w=1328&h=768); React為了大型應(yīng)用而生,Electron和React-native賦予了它構(gòu)建移動端跨平臺App和桌面應(yīng)用的能力,Taro則賦...

    cfanr 評論0 收藏0
  • 如何優(yōu)化你的超大型React應(yīng)用 【原創(chuàng)精讀】

    摘要:往往純的單頁面應(yīng)用一般不會太復(fù)雜,所以這里不引入和等等,在后面復(fù)雜的跨平臺應(yīng)用中我會將那些技術(shù)一擁而上。構(gòu)建極度復(fù)雜,超大數(shù)據(jù)的應(yīng)用。 showImg(https://segmentfault.com/img/bVbvphv?w=1328&h=768); React為了大型應(yīng)用而生,Electron和React-native賦予了它構(gòu)建移動端跨平臺App和桌面應(yīng)用的能力,Taro則賦...

    codecook 評論0 收藏0
  • 如何優(yōu)化你的超大型React應(yīng)用 【原創(chuàng)精讀】

    摘要:往往純的單頁面應(yīng)用一般不會太復(fù)雜,所以這里不引入和等等,在后面復(fù)雜的跨平臺應(yīng)用中我會將那些技術(shù)一擁而上。構(gòu)建極度復(fù)雜,超大數(shù)據(jù)的應(yīng)用。 showImg(https://segmentfault.com/img/bVbvphv?w=1328&h=768); React為了大型應(yīng)用而生,Electron和React-native賦予了它構(gòu)建移動端跨平臺App和桌面應(yīng)用的能力,Taro則賦...

    xiguadada 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<