Context 的作用

给整个组件树共享全局的数据

  1. import React from "react";
  2. import ReactDOM from "react-dom";
  3. const CityContext = React.createContext({
  4. name: "chengdu",
  5. text: "成都",
  6. });
  7. class App extends React.Component {
  8. state = {
  9. cityInfo: {
  10. name: "chengdu",
  11. text: "成都",
  12. },
  13. };
  14. changeCity(cityInfo) {
  15. this.setState({
  16. cityInfo,
  17. });
  18. }
  19. render() {
  20. return (
  21. <CityContext.Provider value={this.state.cityInfo}>
  22. <Header changeCity={this.changeCity.bind(this)} />
  23. <span>{this.state.cityInfo.text}</span>
  24. </CityContext.Provider>
  25. );
  26. }
  27. }
  28. class Header extends React.Component {
  29. render() {
  30. return <Selector changeCity={this.props.changeCity} />;
  31. }
  32. }
  33. class Selector extends React.Component {
  34. // 将上下文的类型指定为 CityContext
  35. // this.context -> CityContext
  36. // 向上找最近的 CityContext 的 Provider,并且取值 cityInfo
  37. /*
  38. contextType
  39. class 的静态属性
  40. 在 ES3 就是 Selector.contextType
  41. 必需指向由 React.createContext 生成的 Context 对象
  42. static contextType = CityContext;
  43. 给当前环境下的 context 重新指定引用
  44. this 下的 context 为 CityContext
  45. 在生命周期函数和 render 函数中都可以访问
  46. */
  47. static contextType = CityContext;
  48. componentDidMount() {
  49. console.log(this.context);
  50. }
  51. render() {
  52. return (
  53. <select
  54. value={this.context.name}
  55. onChange={(e) =>
  56. this.props.changeCity({
  57. name: e.target.value,
  58. text: e.target[e.target.selectedIndex].text,
  59. })
  60. }
  61. >
  62. <option value="beijing">北京</option>
  63. <option value="chengdu">成都</option>
  64. <option value="hangzou">杭州</option>
  65. <option value="shenzhen">深圳</option>
  66. </select>
  67. );
  68. }
  69. }
  70. ReactDOM.render(<App />, document.getElementById("app"));

最适合的场景

杂乱无章的组件都需要同一些数据,
单纯为了不层层传递属性的话,Context 实际上是不合适的 (像纯函数般,不污染组件)

Context 弱点

弱化及污染组件的纯度,导致组件利用性降低。

组合的方法更为适合

  1. import React from 'react';
  2. import ReactDOM from 'react-dom';
  3. class App extends React.Component {
  4. constructor(props) {
  5. super(props);
  6. this.CitySelector = (
  7. <Selector
  8. cityData={this.state.cityData}
  9. cityInfo={this.state.cityInfo}
  10. changeCity={this.changeCity.bind(this)}
  11. />
  12. );
  13. }
  14. state = {
  15. headerTitle: '这是标题',
  16. cityInfo: {
  17. name: 'chengdu',
  18. text: '成都',
  19. },
  20. cityData: [
  21. {
  22. name: 'beijing',
  23. text: '北京',
  24. },
  25. {
  26. name: 'chengdu',
  27. text: '成都',
  28. },
  29. {
  30. name: 'hangzou',
  31. text: '杭州',
  32. },
  33. {
  34. name: 'shenzhen',
  35. text: '深圳',
  36. },
  37. ],
  38. };
  39. changeCity(cityInfo) {
  40. this.setState({
  41. cityInfo,
  42. });
  43. }
  44. render() {
  45. return (
  46. <>
  47. <Header
  48. text={this.state.headerTitle}
  49. citySelector={this.CitySelector}
  50. ></Header>
  51. <span>{this.state.cityInfo.text}</span>
  52. </>
  53. );
  54. }
  55. }
  56. class Header extends React.Component {
  57. render() {
  58. return (
  59. <header>
  60. <h1>{this.props.text}</h1>
  61. <div>{this.props.citySelector}</div>
  62. </header>
  63. );
  64. }
  65. }
  66. class Selector extends React.Component {
  67. render() {
  68. return (
  69. <select
  70. defaultValue={this.props.cityInfo.name}
  71. onChange={(e) => {
  72. this.props.changeCity({
  73. name: e.target.value,
  74. text: e.target[e.target.selectedIndex].text,
  75. });
  76. }}
  77. >
  78. {this.props.cityData.map((item, index) => {
  79. return (
  80. <option value={item.name} key={index}>
  81. {item.text}
  82. </option>
  83. );
  84. })}
  85. </select>
  86. );
  87. }
  88. }
  89. ReactDOM.render(<App />, document.getElementById('app'));