React进阶(十三):Context

x33g5p2x  于2021-11-11 转载在 React  
字(4.3k)|赞(0)|评价(0)|浏览(657)

前言

Context 提供了一种方式,能够让数据在组件树中传递时不必一级一级的手动传递。

一般情况下,数据在组件中,要一级一级的传递,单向数据流,比如Parent组件中的theme值,需要在Item组件中使用,就需要我们从Parent中向下传递, 但当我们有了Context后,我们就不需要一级一级传递了。

  1. Parent(theme=red)
  2. List(theme=red)
  3. Item(theme=red)
  4. ThemeContext.Provider value={'red'}
  5. List
  6. ThemeContext.Customer (theme) => { theme }

具体如何使用呢,看下面例子:

  1. import React, { createContext } from 'react';
  2. // 创建Context的唯一方法
  3. const ThemeContext = createContext()
  4. class App extends React.Component {
  5. render () {
  6. return (
  7. // 使用 Context.Provider 包裹后续组件,value指定值
  8. <ThemeContext.Provider value={'red'}>
  9. <Middle></Middle>
  10. </ThemeContext.Provider>
  11. )
  12. }
  13. }
  14. class Bottom extends React.Component {
  15. render () {
  16. return (
  17. // Context.Consumer Consumer消费者使用Context的值
  18. // 但子组件不能是其他组件,必须渲染一个函数,函数的参数就是Context的值
  19. <ThemeContext.Consumer>
  20. {
  21. theme => <h1>ThemeContext的值为{theme}</h1>
  22. }
  23. </ThemeContext.Consumer>
  24. )
  25. }
  26. }
  27. class Middle extends React.Component {
  28. render () {
  29. return <Bottom></Bottom>
  30. }
  31. }
  32. export default App;

Provider 提供的值更改时,Consumer必须重新渲染!

  1. import React, { createContext } from 'react';
  2. // 创建Context的唯一方法
  3. const ThemeContext = createContext()
  4. class App extends React.Component {
  5. state = {
  6. theme: 'red'
  7. }
  8. render () {
  9. const { theme } = this.state
  10. return (
  11. // 使用 Context.Provider包裹后续组件,value指定值
  12. <ThemeContext.Provider value={theme}>
  13. {/* 当Context的Provider值更改时,Consumer 的值必须重新渲染 */}
  14. <button onClick={() => {this.setState({ theme: 'yellow'})}}>按钮</button>
  15. <Middle></Middle>
  16. </ThemeContext.Provider>
  17. )
  18. }
  19. }
  20. class Bottom extends React.Component {
  21. render () {
  22. return (
  23. // Context.Consumer Consumer消费者使用Context的值
  24. // 但子组件不能是其他组件,必须渲染一个函数,函数的参数就是Context的值
  25. <ThemeContext.Consumer>
  26. {
  27. theme => <h1>ThemeContext的值为{theme}</h1>
  28. }
  29. </ThemeContext.Consumer>
  30. )
  31. }
  32. }
  33. class Middle extends React.Component {
  34. render () {
  35. return <Bottom></Bottom>
  36. }
  37. }
  38. export default App;

当出现多个Context的时候,应该如何使用呢?

  1. import React, { createContext } from 'react';
  2. // 创建Context的唯一方法
  3. const ThemeContext = createContext()
  4. const SizeContext = createContext()
  5. class App extends React.Component {
  6. state = {
  7. theme: 'red',
  8. size: 'small'
  9. }
  10. render () {
  11. const { theme, size } = this.state
  12. return (
  13. // 使用Context.Provider包裹后续组件,value指定值
  14. <ThemeContext.Provider value={theme}>
  15. {/* 当出现多个Context的时候,只需要将Context.Provider嵌套即可 */}
  16. <SizeContext.Provider value={size}>
  17. {/* 当Context的Provider值更改时,Consumer的值必须重新渲染 */}
  18. <button onClick={() => {this.setState({ theme: 'yellow', size: 'big'})}}>按钮</button>
  19. <Middle></Middle>
  20. </SizeContext.Provider>
  21. </ThemeContext.Provider>
  22. )
  23. }
  24. }
  25. class Bottom extends React.Component {
  26. render () {
  27. return (
  28. // Context.Consumer Consumer消费者使用Context得值
  29. // 但子组件不能是其他组件,必须渲染一个函数,函数的参数就是Context的值
  30. // 当出现多个Consumer的时候,进行嵌套,每个Consumer的子组件必须是一个函数,即可
  31. <ThemeContext.Consumer>
  32. {
  33. theme => (
  34. <SizeContext.Consumer>
  35. {
  36. size => (<h1>ThemeContext 值为 {theme}; SizeContext 的值为 {size}</h1>)
  37. }
  38. </SizeContext.Consumer>
  39. )
  40. }
  41. </ThemeContext.Consumer>
  42. )
  43. }
  44. }
  45. class Middle extends React.Component {
  46. render () {
  47. return <Bottom></Bottom>
  48. }
  49. }
  50. export default App;

Consumer 向上找不到 Provider 的时候,怎么办?react 并不会报错,只不过取不到值而已。所以,创建 Context 的时候 createContext 可以传入默认值,当找不到 Provider 的时候,就会显示默认值。

注意:context 类似于全局变量做法,会让组件失去独立性、复用起来更困难,不能滥用,但本身它一定有适合使用的场景,具体看情况使用。

contextType

contextType 可以简化 context 的使用,不使用 consumer 也可以共享变量。

具体看下面例子

  1. import React, { createContext } from 'react';
  2. // 创建Context的唯一方法
  3. const ThemeContext = createContext()
  4. const SizeContext = createContext()
  5. class App extends React.Component {
  6. state = {
  7. theme: 'red',
  8. size: 'small'
  9. }
  10. render () {
  11. const { theme, size } = this.state
  12. return (
  13. // 使用Context.Provider包裹后续组件,value指定值
  14. <ThemeContext.Provider value={theme}>
  15. {/* 当出现多个Context的时候,只需要将Context.Provider嵌套即可 */}
  16. <SizeContext.Provider value={size}>
  17. {/* 当Context的Provider值更改时,Consumer的值必须重新渲染 */}
  18. <button onClick={() => {this.setState({ theme: 'yellow', size: 'big'})}}>按钮</button>
  19. <Middle></Middle>
  20. </SizeContext.Provider>
  21. </ThemeContext.Provider>
  22. )
  23. }
  24. }
  25. class Bottom extends React.Component {
  26. // 声明静态变量,contextType 将 context 直接赋值于 contextType
  27. static contextType = ThemeContext
  28. render () {
  29. // 在render函数中可以直接访问this.context获取共享变量,这样就可以不使用consumer
  30. const theme = this.context
  31. return (
  32. // Context.Consumer Consumer消费者使用Context的值
  33. // 但子组件不能是其他组件,必须渲染一个函数,函数的参数就是Context的值
  34. // 当出现多个Consumer的时候,进行嵌套,每个Consumer的子组件必须是一个函数,即可
  35. <div>
  36. <h1>ThemeContext的值为{theme} </h1>
  37. </div>
  38. )
  39. }
  40. }
  41. class Middle extends React.Component {
  42. render () {
  43. return <Bottom></Bottom>
  44. }
  45. }
  46. export default App;

注意:
contextType 只能在类组件中使用, 一个组件如果有多个 consumercontextType只对其中一个有效,所以说,contextType 只能有一个!

拓展阅读

  • 《React进阶(十二):HOOK》

相关文章

最新文章

更多