摘要:作為數據的發布方,它擁有一個名為的屬性,用于維護數據內容,通過傳遞給的數據會被發布出去。最后,組件將自己的原封不動的傳遞給。但是通過這次的實踐,也算是熟悉的的用法,對也加深了了解吧。
這是一篇我發在掘金上的文章,原文有一個我沒有解決的問題,在網友的解答下我找到了答案,我把文章重新修改編輯后,同步發送到這里,希望能對大家有所幫助。
本文原發布于掘金:https://juejin.im/post/5a900d...
最近接到一個簡單的內部項目,邏輯并不復雜,就想著不用redux了,用react的new context API試試看,折騰了兩天,把過程和感想跟大家分享下。
由于是公司的項目,所以下文的示例代碼都是我重新寫的,望見諒!
基本用法首先,讓我們來看一下這個接口的基本用法:
使用它首先需要使用react的createContext方法創建一個實例:
import React, { createContext } from "react"; const Context = createContext({ gender: "male" });;
Context實例提供兩個組件:Provider和Consumer
const ContextProvider = Context.Provider; const ContextConsumer = Context.Consumer;
其中ContextProvider是數據的發布方,而ContextConsumer是數據的訂閱方。
{ context => ( name: {context.name} age: {context.age}) }
ContextProvider作為數據的發布方,它擁有一個名為value的屬性,用于維護數據內容,通過value傳遞給ContextProvider的數據會被發布出去。
而ContextConsumer作為數據的訂閱方,它的props.children是一個函數,接收的參數是被發布的數據,我們通過調用這個函數來獲取被ContextProvider發布的數據,并且返回我們想要渲染的組件。
在這個示例中,我們最后在頁面上能夠顯示出name: A age: 18。
關于調用createContext方法時候的傳參,理論上第一個傳參應該是初始化的數據,但是我使用后發現,如果在ContextProvider的value屬性中不傳入對應的屬性的話,無法在ContextConsumer中獲取到那個初始化的屬性。
const Context = createContext({ gender: "male" });{ context => ( name: {context.name} age: {context.age}) }
這個例子中,我始終無法獲取到gender的值。
我目前還沒找到原因,如果知道的朋友請告訴我一下,謝謝!
經過網友的解答和我自己的試驗,這個問題得到了解答:
Provider的value屬性會把初始化Context時傳遞的初始狀態給覆蓋掉;
如果想要使用初始的狀態,那么就不能使用Provider,也就是說,只有訂閱數據而不發布新數據的情況下,初始的狀態才會有效;
實踐為了適應項目的需求,我主要是對ContextProvider和ContextConsumer做了封裝。
ContextProvider由于在我的項目中組件需要訂閱并且修改和維護被發布的數據,所以我需要有一個可以維護這些數據的地方。因此我創建了一個名為MyProvider的高階組件,并把它放在組件樹的頂層,而各個組件需要訂閱的數據就存放在MyProvider的state中,那么我只需要維護它的state就能維護這些全局的數據了。
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作為要發布的數據綁定到了ContextProvider的value屬性上。
前面講過,由于其他組件有要修改被發布數據的需求,所以我給數據添加了一個不可修改的方法updateContext,這個方法能夠接收新的數據并更新MyProvider的state,即更新了被發布的數據。
最后,MyProvider組件將自己的children原封不動的傳遞給ContextProvider。
考慮到ContextConsumer作為訂閱方使用比較頻繁,為了方便其他組件的使用,我將它封裝到高階組件中,并作為函數的返回值使用,如下:
export const MyConsumer = Component => { return props => ({context => { return ); };; }}
MyConsumer函數返回一個高階組件。在這個高階組件中,我把ContextConsumer提供的數據加入到Component的props中,這樣我只需要在export組件的時候調用MyConsumer,并且在組件中使用this.props.context.data就能得到被發布的數據了。如下:
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);
在這個例子中,點擊按鈕,調用this.props.context.updateContext方法就可以通過更新MyProvider的state來修改被發布數據中的age的值。
示例代碼:react-new-context-api-demo
小結我折騰了兩天之后才反應過來,這不就是一個類似于redux的東西嗎?
可能由于我redux用的多了,對于Prvider和Consumer的封裝下意識的做成了類似redux的用法。再加上使用MyProvider的state作為唯一數據源,又有updateContext這個有點像dispatch的方法來更新數據,乍一看之下,還是有點redux的影子的。
當然了,我自己寫的完全沒有redux那么好用,也沒有reudx那么嚴謹。所以,后來我又花了一個上午的時間改用了redux。
但是通過這次的實踐,也算是熟悉的new context api的用法,對redux也加深了了解吧。
最后,如果你只是想要訂閱數據,new context api是個不錯的選擇;但是如果你想要修改和維護被發布的數據,使用redux會更方便和安全。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/95115.html
摘要:觀察者模式,一次創建多條通信鏈路,每條鏈路工作時與其他鏈路發生干擾。在目前系統中,只存在兄弟通信和父子通信,不存在跨樹通信,即孩子不能跟叔叔直接通信。模擬操作的方式,歸根到底是把手動測試過程用腳本記錄下來。 作者:BrianLi (部門同事李老師,口頭授權發布內部react布道資料) 無法用語言準確表達思維時,就用公式;一個不行,那就兩個 —— 李老師 本文假設讀者已了解react的基...
摘要:之前做的一個應用,最近把首頁改成了服務端渲染的形式,過程還是很周折的,踩到了不少坑,記錄一些重點,希望有所幫助前端使用的技術棧升級到升級到服務項目地址喜歡的給個,感謝。。。。。。。 之前react做的一個應用,最近把首頁改成了服務端渲染的形式,過程還是很周折的,踩到了不少坑,記錄一些重點,希望有所幫助 前端使用的技術棧 react、react-dom 升級到 v16 react-ro...
摘要:往往純的單頁面應用一般不會太復雜,所以這里不引入和等等,在后面復雜的跨平臺應用中我會將那些技術一擁而上。構建極度復雜,超大數據的應用。 showImg(https://segmentfault.com/img/bVbvphv?w=1328&h=768); React為了大型應用而生,Electron和React-native賦予了它構建移動端跨平臺App和桌面應用的能力,Taro則賦...
摘要:往往純的單頁面應用一般不會太復雜,所以這里不引入和等等,在后面復雜的跨平臺應用中我會將那些技術一擁而上。構建極度復雜,超大數據的應用。 showImg(https://segmentfault.com/img/bVbvphv?w=1328&h=768); React為了大型應用而生,Electron和React-native賦予了它構建移動端跨平臺App和桌面應用的能力,Taro則賦...
摘要:往往純的單頁面應用一般不會太復雜,所以這里不引入和等等,在后面復雜的跨平臺應用中我會將那些技術一擁而上。構建極度復雜,超大數據的應用。 showImg(https://segmentfault.com/img/bVbvphv?w=1328&h=768); React為了大型應用而生,Electron和React-native賦予了它構建移動端跨平臺App和桌面應用的能力,Taro則賦...
閱讀 817·2021-10-13 09:39
閱讀 3697·2021-10-12 10:12
閱讀 1741·2021-08-13 15:07
閱讀 1006·2019-08-29 15:31
閱讀 2883·2019-08-26 13:25
閱讀 1776·2019-08-23 18:38
閱讀 1879·2019-08-23 18:25
閱讀 1857·2019-08-23 17:20