用componentdidupdate反应上下文

时间:2018-11-22 00:57:59

标签: reactjs lifecycle

我正在运行类似的模式,假设安装了SearchResultsContainer,并且在搜索栏的某个位置设置了输入。

class SearchResults {
   render() {
      return(
        <ResultsContext.Consumer value={input}>
        {input => <SearchResultsContainer input=input}
        </ResultsContext.Consumer>
   )
}

class SearchResultsContainer
  componentDidUpdate() {
      //fetch data based on new input
      if (check if data is the same) {
        this.setState({
          data: fetchedData
        })
      }
  }
}

这将在调用新的上下文值时调用两次提取,因为componentDidUpdate()将触发并设置数据。在来自结果上下文的新输入中,它将调用componentDidUpdate(),获取并设置数据,然后调用componentDidUpdate(),并获取,然后检查数据是否相同并停止循环。

这是使用上下文的正确方法吗?

3 个答案:

答案 0 :(得分:0)

我使用的解决方案是通过高阶组件将上下文传输到道具。

我使用了这个非常有用的github答案https://github.com/facebook/react/issues/12397#issuecomment-374004053

结果看起来像这样: my-context.js

import React from "react";

export const MyContext = React.createContext({ foo: 'bar' });

export const withMyContext = Element => {
  return React.forwardRef((props, ref) => {
    return (
      <MyContext.Consumer>
        {context => <Element myContext={context} {...props} ref={ref} />}
      </MyContext.Consumer>
    );
  });
};

另一个消耗上下文的组件:

import { withMyContext } from "./path/to/my-context";

class MyComponent extends Component {
 componentDidUpdate(prevProps) {
    const {myContext} = this.props
    if(myContext.foo !== prevProps.myContext.foo){
      this.doSomething()
    }
  }
}
export default withMyContext(MyComponent);

在某处必须有一个上下文生成器:

<MyContext.Provider value={{ foo: this.state.foo }}>
  <MyComponent />
</MyContext.Provider>

答案 1 :(得分:0)

这是一种方法,不需要手动将上下文从父级传递到组件props。

// Context.js

import { createContext } from 'react'

export const Context = createContext({ example: 'context data' })

// This helps keeps track of the previous context state
export class OldContext {
    constructor(context) {
        this.currentContext = context
        this.value = {...context}
    }
    update() {
        this.value = {...this.currentContext}
    }
    isOutdated() {
        return JSON.stringify(this.value) !== JSON.stringify(this.currentContext)
    }
}
// ContextProvider.js

import React, { Component } from 'react'
import { Context } from './Context.js'
import { MyComponent } from './MyComponent.js'

export class ContextProvider extends Component {
    render(){
        return (
            <MyContext.provider>
                {/* No need to pass context into props */}
                <MyComponent />
            </MyContext.provider>
        )
    }
}
// MyComponent.js

import React, { Component } from 'react'
import { Context, OldContext } from './Context.js'

export class MyComponent extends Component {
    static contextType = Context

    componentDidMount() {
        this.oldContext = new OldContext(this.context)
    }

    componentDidUpdate() {
        // Do all checks before updating the oldContext value
        if (this.context.example !== this.oldContext.value.example) {
            console.log('"example" in context has changed!')
        }

        // Update the oldContext value if the context values have changed
        if (this.oldContext.isOutdated()) {
            this.oldContext.update()
        }
    }

    render(){
        return <p>{this.props.context.example}</p>
    }
}

答案 2 :(得分:0)

您可以仅传递单独更改的值作为道具。

ProjectEmployeeRole

范围->道具包装似乎是反应人员推荐的。但是,他们似乎并没有解决将上下文包装在道具中然后直接从孩子的孩子那里消费上下文等问题。

如果您有许多这样的道具需要观察,尤其是当不仅仅是组件树的分支末端时,请查看Redux,它比React.extent内置的功能更强大。