So let’s talk about what Context does

MVVM frameworks like React have a pain point that everyone has encountered, and that is communication between grandparent and grandchild components

The current communication specification between components is:

  • Parent -> Child: property binding props
  • Child -> parent: event broadcast (emit, etc.) React That is still calling the parent class props[fn]

Just between parent and child components that’s fine but between grandparent components?

React has a wormhole concept, which is equivalent to a through-train, component ancestor => component grandson, and does not need an intermediate component to act as props

Let’s take a look at high-end wormholes.

Directly show code

Js, GrandSon. Js, GrandSon. Js, GrandSon

// app.js code import React from'react';
import Son from './son';
import PropTypes from 'prop-types';

class App extends React.Component{
    constructor(){
		super();
		
        this.state = {
            grandSonDesc: 'i am grandSonDesc'
        };
    }

    getChildContext() {return {
            grandSonDesc: this.state.grandSonDesc
        }
    }
    
    render() {return <Son />
    }
}

App.childContextTypes = {
    grandSonDesc: PropTypes.string
}

export default App;
Copy the code
// Son.js

import React from 'react';
import GrandSon from './grandSon';

const Son = () => {
    return <GrandSon />
}

export default Son;
Copy the code
// GrandSon.js

import React from 'react';
import PropTypes from 'prop-types';

class GrandSon extends React.Component{
    render() {return <div>{this.context.grandSonDesc}</div>
    }
}

GrandSon.contextTypes = {
    grandSonDesc: PropTypes.string
};

export default GrandSon;
Copy the code

The wormhole is now implemented, but two points need to be noted:

  • GrrandSon cannot be a purely functional component, so it cannot be injected
  • The App and GrandSon components need to define contextTypes, and the App component needs to define getChildContext

So why declare contextTypes? The reason is that apart from App, the GrandSon component is also the Son component. Which component does grandSonDesc inherit from? ContextTypes is used for this purpose, and multiple parent contexts merge contextTypes according to the definition of contextTypes

Ok, it feels great to be here, but I want to say that this implementation will be deprecated in Act17!!

Why are old wormholes being scrapped?

If an attribute is about to be deprecated, it is probably related to its performance. If the son component of the wormhole transport props is not updated, will the son component be updated when grandSonDesc changes? Just show code

// App.js

import React from 'react';
import Son from './son';
import PropTypes from 'prop-types';

class App extends React.Component{
    constructor(){
		super();
		
        this.state = {
            grandSonDesc: 'i am grandSonDesc'
        };
	}
	
	componentDidMount() {setTimeout(() => {
			this.setState({
				grandSonDesc: 'I am grandSonDesc aaah aaah aaah'
			});
		}, 3000);
	}

    getChildContext() {return {
            grandSonDesc: this.state.grandSonDesc
        }
    }
    
    render() {return <Son />
    }
}

App.childContextTypes = {
    grandSonDesc: PropTypes.string
}

export default App;
Copy the code
// Son.js

import React from 'react';
import GrandSon from './grandSon';

class Son extends React.Component{
    componentDidUpdate(){
        console.log('son updated! ');
    }

    render() {return <GrandSon />
    }
}

export default Son;
Copy the code
// GrandSon.js

import React from 'react';
import PropTypes from 'prop-types';

class GrandSon extends React.Component{
    componentDidUpdate(){
        console.log('grandson updated! ');
    }

    render() {return <div>{this.context.grandSonDesc}</div>
    }
}

GrandSon.contextTypes = {
    grandSonDesc: PropTypes.string
};

export default GrandSon;
Copy the code

In the version code, app.js updates grandSonDesc after three seconds, and then adds componentDidUpdate logs to Son and GrandSon components to see the console output

This means that the Son component has also been updated, so if the wormhole has a lot of mid-tier components, wouldn’t it be a waste of performance?

The second generation wormhole

What’s the problem? What’s the problem? What’s the problem? What’s the problem

// App.js

import React from 'react';
import Son from './son';
import Context from './context';
import PropTypes from 'prop-types';

class App extends React.Component {
    constructor(){
        super();

        this.state = {
            grandSonDesc: 'i am grandSon'
        };
    }

	render() {return (
			<div className="App">
				<Context.Provider value={this.state}>
					<Son />
				</Context.Provider>
			</div>
		);
	}
}

App.contextType = Context;

export default App;
Copy the code
// Son.js

import React, { PureComponent } from 'react';
import GrandSon from './grandSon';
import PropTypes from 'prop-types';

class Son extends PureComponent{
    render() {return <GrandSon />
    }
}

export default Son;
Copy the code
// GrandSon.js

import React, { PureComponent } from 'react';
import Context from './context';

class GrandSon extends PureComponent{
    render() {return <div>
            <Context.Consumer>
                {value => value.grandSonDesc}
            </Context.Consumer>
        </div>
    }
}

export default GrandSon
Copy the code
// context.js

import { createContext } from 'react';

let Context = createContext();

export default Context;
Copy the code

The code is finished, you can start to see the effect, you can find that it still runs

Which begs the question, why do you think the first wormhole is bad?

// App.js

import React from 'react';
import Son from './son';
import Context from './context';
import PropTypes from 'prop-types';

class App extends React.Component {
    constructor(){
        super();

        this.state = {
            grandSonDesc: 'i am grandSon'
        };
    }

    componentDidMount() {setTimeout(() => {
            this.setState({
                grandSonDesc: 'I am Goh goh goh goh goh goh'
            });
        }, 3000);
    }

	render() {return (
			<div className="App">
				<Context.Provider value={{grandSonDesc: this.state.grandSonDesc}}>
					<Son />
				</Context.Provider>
			</div>
		);
	}
}

App.contextType = Context;

export default App;

Copy the code
// Son.js

import React, { PureComponent } from 'react';
import GrandSon from './grandSon';
import PropTypes from 'prop-types';

class Son extends PureComponent{
    componentDidUpdate(){
        console.log('son updated');
    }

    render() {return <GrandSon />
    }
}

export default Son;
Copy the code
// GrandSon.js

import React, { PureComponent } from 'react';
import Context from './context';

class GrandSon extends PureComponent{
    componentDidUpdate(){
        console.log('grandson updated');
    }

    render() {return <div>
            <Context.Consumer>
                {value => value.grandSonDesc}
            </Context.Consumer>
        </div>
    }
}

export default GrandSon
Copy the code

It can be found that grandSonDesc changed after 3 seconds, and the componentDidUpdated of the two sub-components did not enter

That’s how the two wormholes are implemented, and that’s about it. For more information on how to use the new context, see reactjs.org/docs/contex…