国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

react-dnd中context丟失解決方法

Arno / 3079人閱讀

摘要:等等這不就用的將的給覆蓋了么這也很合理的解釋了為啥會(huì)報(bào)錯(cuò)了。嗯還是拿不到,想起來了,雖然將靜態(tài)屬性拿了出來,但是原型方法不會(huì)拿出來啊,所以的就沒用了,所以我們需要也將他拿出來,于是,加上一下代碼這次總算拿到正確的結(jié)果了,開心

踩坑場(chǎng)景

在做業(yè)務(wù)的時(shí)候,有些模塊是可以拖動(dòng)的,恰好這些模塊需要從根組件App的context上拿屬性,同時(shí)App也是作為拖動(dòng)上下文,被@DragDropContext(HTML5Backend)裝飾,當(dāng)時(shí)年少無知,無腦寫下了以下代碼

const boxSource = {
  canDrag(props, monitor) {
    ...
  },
  beginDrag(props) {
   ...
  },
  endDrag(props, monitor) {
 ...
  },
};
@DragSource("box", boxSource, (connect, monitor) => ({
  connectDragSource: connect.dragSource(),
  isDragging: monitor.isDragging(),
}))
export default class Box extends Component {
 static contextTypes = {
  value: PropTypes.number
};
  static propTypes = {
    ...
  }
  render() {
    const { isDragging, connectDragSource, src } = this.props;
    const { value } = this.context;
    return (
      connectDragSource(
        ...
      )
    );
  }
}

美滋滋啊,美滋滋啊,so ez,會(huì)用react-dnd了,趕緊將代碼跑起來,結(jié)果傻眼了,居然報(bào)這個(gè)錯(cuò)誤

Invariant Violation: Could not find the drag and drop manager in the context of Box. Make sure to wrap the top-level component of your app with DragDropContext. Read more: http://react-dnd.github.io/react-dnd/docs-troubleshooting.html#could-not-find-the-drag-and-drop-manager-in-the-context

提示我們?cè)谕献ЫM件Box的context上找不到react-dnd需要的drag and drop manager,懵了,讓我想想是咋回事,是不是最后給

  static contextTypes = {
    value: PropTypes.number
  }

給覆蓋了原來的Box.contextTypes呀?
不過這也簡(jiǎn)單,不讓他覆蓋就好了嘛,于是我寫下了如下的代碼

Box.contextTypes = Object.assign(Box.contextTypes,{
  value: PropTypes.number
});

真好,報(bào)錯(cuò)消失了,大功告成!等等,this.context.value怎么是undefined,拿不到了?我明明在contextTypes里聲明了呀,不行,還是得去看一看源碼。

React-dnd源碼

查看DragSource的源碼,可以看到DragSource就是一個(gè)普通裝飾器包裝函數(shù)

function DragSource(type, spec, collect, options = {}) {
...
return function decorateSource(DecoratedComponent) {
    return decorateHandler({
      connectBackend: (backend, sourceId) => backend.connectDragSource(sourceId),
      containerDisplayName: "DragSource",
      createHandler: createSource,
      registerHandler: registerSource,
      createMonitor: createSourceMonitor,
      createConnector: createSourceConnector,
      DecoratedComponent,
      getType,
      collect,
      options,
    });
  };
}

那我們繼續(xù)去看一看 decorateHandler這個(gè)函數(shù)唄

export default function decorateHandler({
  DecoratedComponent,
  createHandler,
  createMonitor,
  createConnector,
  registerHandler,
  containerDisplayName,
  getType,
  collect,
  options,
}) {
...
 class DragDropContainer extends Component {
  ...
    static contextTypes = {
      dragDropManager: PropTypes.object.isRequired,
    }
  ...
    render() {
      return (
        
        );
      }
    }

    return hoistStatics(DragDropContainer, DecoratedComponent);
}

嗯, decorateHandler就是一個(gè)HOC生成函數(shù)嘛,hoistStatics就是hoist-non-react-statics這個(gè)庫(kù),做過HOC的童鞋一定不陌生,他就是將WrappedComponent的靜態(tài)方法和靜態(tài)屬性提到HOC上,面,避免WrappedComponent的靜態(tài)屬性和靜態(tài)方法丟失了,看似挺合理,嗯嗯。等等!這不就用WrappedComponent的contextTypes將HOC的contextTypes給覆蓋了么?這也很合理的解釋了為啥會(huì)報(bào)錯(cuò)了。

解決步驟

知道了其中的原來,那我們就讓HOC和WrappedComponent各自保留一份contextTypes好了,首先我們需要用另一個(gè)變量來保留對(duì)WrappedComponent的引用,因?yàn)楸?b>@DragSource裝飾后,WrappedComponent的變量名就會(huì)被HOC覆蓋了,然后我們?cè)賹?duì)WrappedComponent加上contextTypes就好了,代碼如下:

class Box extends Component {
  static propTypes = {
    connectDragSource: PropTypes.func.isRequired,
    ...
  }
  render() {
    const { isDragging, connectDragSource, src } = this.props;
    const { value } = this.context;
   ...
    return (
      connectDragSource(
       ...
      )
    );
  }
}

const Temp = Box;
const Box1 = DragSource("box", boxSource, (connect, monitor) => ({
  connectDragSource: connect.dragSource(),
  isDragging: monitor.isDragging(),
}))(Box);
Temp.contextTypes = {
  value: PropTypes.number,
}
export default Box1;

大功告成,我們?cè)賮砼芤慌堋?br>哇,又報(bào)錯(cuò)了,囧,說

Invariant Violation: App.getChildContext(): childContextTypes must be defined in order to use getChildContext().

好,那我們來看看根組件咋回事,我寫的根組件如下

@DragDropContext(HTML5Backend)
class App extends React.Component {
  constructor(props) {
    super(props);

  }
  static childContextTypes = {
    value:PropTypes.number,
 }
  getChildContext(){
    return {
      value:1
    }
  }

  render() {
    return (
      
    )
  }
}

讓我們看看DragDropContext源碼

export default function DragDropContext(backendOrModule) {
 ...
 return function decorateContext(DecoratedComponent) {
  ...
   class DragDropContextContainer extends Component {
      getChildContext() {
        return childContext;
      }

      render() {
        return (
           { this.child = child; }}
          />
        );
      }
    }

    return hoistStatics(DragDropContextContainer, DecoratedComponent);
  };
}

得,又是HOC的問題,但是有點(diǎn)不同,就是contextTypes一定要準(zhǔn)確設(shè)置在需要的組件上,但是childContextTypes只要放在上層組件就可以了,所以我做了如下修改:

刪去class App 中的

 static childContextType = {
    value: PropTypes.number
  }

加上一下代碼

App.childContextTypes = Object.assign(App.childContextTypes,{
  value: PropTypes.number
});

這次總該行了吧,心累啊。嗯?還是拿不到this.context.value,想起來了!,雖然hoist-non-react-statics將靜態(tài)屬性拿了出來,但是原型方法不會(huì)拿出來啊,所以WrappedComponent的getChildContext就沒用了,所以我們需要也將他拿出來,于是,加上一下代碼

const temp = {...App.prototype.getChildContext()};
App.prototype.getChildContext = () => ({...temp, value:1})

這次總算拿到正確的結(jié)果了,開心

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/87362.html

相關(guān)文章

  • React-dnd實(shí)現(xiàn)拖拽,最簡(jiǎn)單代碼,直接可以跑

    摘要:不多說,直接上代碼需要版本貌似與方法有關(guān)類似的高階組件包裹被拖的元素高階組件包裹被釋放的元素這個(gè)庫(kù)是必須的,類似于的合成事件解決瀏覽器差異,抽象事件操作為可以處理的 不多說,直接上代碼 react-dnd 需要react版本 > 16.6 ,貌似與react.memo方法有關(guān) import React from react // DragDropContext 類似React的Co...

    xiaokai 評(píng)論0 收藏0
  • 使用React DND 完成一個(gè)簡(jiǎn)單的卡片排序功能

    摘要:簡(jiǎn)介在公司初學(xué)其中一個(gè)要求讓我實(shí)現(xiàn)拖拽排序的功能完成之后記錄一下實(shí)現(xiàn)方法,采用和來實(shí)現(xiàn)這個(gè)功能。一環(huán)境搭建首先,使用腳手架創(chuàng)建一個(gè)最基本的項(xiàng)目。 簡(jiǎn)介 在公司初學(xué)react,其中一個(gè)要求讓我實(shí)現(xiàn)拖拽排序的功能,完成之后記錄一下實(shí)現(xiàn)方法,采用antd和reactDND來實(shí)現(xiàn)這個(gè)功能。 一、環(huán)境搭建 首先,使用 create-react-app 腳手架創(chuàng)建一個(gè)最基本的react項(xiàng)目。 np...

    edgardeng 評(píng)論0 收藏0
  • React context 丟失問題

    摘要:丟失問題文本是為了說清目前的機(jī)制是而不是我們以為的機(jī)制,并說明這兩者的區(qū)別。雖然明白了原理,但是問題并沒有解決。上下文注意這里是,需要執(zhí)行接受回調(diào)函數(shù),回調(diào)函數(shù)中的內(nèi)容為實(shí)測(cè)可以成功拿到。 React context 丟失問題 文本是為了說清react context目前的機(jī)制是owner context 而不是我們以為的parent context 機(jī)制,并說明這兩者的區(qū)別。...

    Seay 評(píng)論0 收藏0
  • 聊一聊我對(duì) React Context 的理解以及應(yīng)用

    摘要:假如以的作用域鏈作為類比,組件提供的對(duì)象其實(shí)就好比一個(gè)提供給子組件訪問的作用域,而對(duì)象的屬性可以看成作用域上的活動(dòng)對(duì)象。所以,我借鑒了作用域鏈的思路,把當(dāng)成是組件的作用域來使用。 前言 Context被翻譯為上下文,在編程領(lǐng)域,這是一個(gè)經(jīng)常會(huì)接觸到的概念,React中也有。 在React的官方文檔中,Context被歸類為高級(jí)部分(Advanced),屬于React的高級(jí)API,但官方...

    chengjianhua 評(píng)論0 收藏0
  • 【前端面試】作用域和閉包

    摘要:作用域沒有塊級(jí)作用域盡量不要在塊中聲明變量。只有函數(shù)級(jí)作用域作用域鏈自由變量當(dāng)前作用域沒有定義的變量即為自由變量。自由變量會(huì)去其父級(jí)作用域找。 1. 題目 說一下對(duì)變量提升的理解 說明this的幾種不同使用場(chǎng)景 創(chuàng)建10個(gè)a標(biāo)簽,點(diǎn)擊的時(shí)候彈出來相應(yīng)的序號(hào) 如何理解作用域 實(shí)際開發(fā)中閉包的應(yīng)用 手動(dòng)實(shí)現(xiàn)call apply bind 2. 知識(shí)點(diǎn) 2.1 執(zhí)行上下文 范圍:一段scri...

    yanest 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<