If you don’t want to see the joke, you can skip it and check the topic.
Why use providers
Internal projects manage global state in three places
- Window. – Sounds like it makes sense
- LocalStorage – Nothing wrong with old iron
- Url – I can’t find anything. What’s the problem
The problem is not the way to access the state, but using three different methods at once. Well, I admit it, I lost it. The overall project code is full of such code, it is said that the project or Ali open source, I Buddha gas! Stick a picture, say without proof
constructor(props) {
super(props);
this.deleteDialog = React.createRef();
this.showcode = React.createRef();
this.field = new Field(this);
this.appName = getParams('appName') || getParams('edasAppId') | |' ';
this.preAppName = this.appName;
this.group = getParams('group') | |' ';
this.preGroup = this.group;
this.dataId = getParams('dataId') | |' ';
this.preDataId = this.dataId;
this.serverId = getParams('serverId') | |'center';
this.edasAppId = getParams('edasAppId') | |' ';
this.edasAppName = getParams('edasAppName') | |' '; }}Copy the code
What is getParams? Get the value of the corresponding parameter from the URL, you guessed it, if you want to add a global state variable there’s also a setParams method. The big guy is all things considered.
If you’re used to the React-Router, you might be wondering: Why don’t arguments be taken from match?
const MENU = [
{ path: '/'.exact: true.render: (a)= > <Redirect to="/configurationManagement" /> },
{ path: '/namespace'.component: Namespace },
{ path: '/newconfig'.component: Newconfig },
{ path: '/configsync'.component: Configsync },
...
]
Copy the code
You guessed it, the whole route doesn’t match any parameters, don’t talk to me about match, the URL doesn’t work. 🌹 🐔
At this point, it’s up to the great URL to maintain the global state variables.
What is the cost of state maintenance with urls?
That means I have to listen to the URL all the time, get the parameters I want, and update the values. If you are unlucky, you may need to update Windows or localStorage (it is not that it cannot be used), so I set a 4-day schedule for the project to solve the confusion of the unified state, which was reduced to 1 day. Well. It’s not like it doesn’t work.
Topic, use Provider
Knowing my pain above, I was only given one day later, so my solution was born. The Provider, live forever! (As an aside, react-Redux was used in the project, and providers were also used, which didn’t play their due value.)
The Provider API analysis
- The React. CreateContext create Context
- Context.Provider modifies the value property to dynamically change the Context
- ContextType: contextType: contextType: contextType: contextType: contextType: contextType: contextType: contextType: contextType: contextType
- Context.Consumer this method is used to enable components to subscribe to multiple contexts
Static by value
Static value transfer is not very special. Call react. createContext(defaultValue) and write defaultValue directly to pass the value.
The dynamic change of
Dynamic changes usually do not operate on the context in a file. In this case, you need to create the context in a third-party file. The nav-context.js file is shown below
import React from 'react';
export const NavContext = React.createContext({
handleNavChange: (a)= >{}});Copy the code
Then import the context in the file that you want to use. And change its value, refer to the official example
<ThemeContext.Provider value={this.state.theme}>
<Toolbar changeTheme={this.toggleTheme} />
</ThemeContext.Provider>
Copy the code
In this case, the default value of the context is set to this.state.theme. This extends to passing events so that in other components, you can call that event. In the actual reference file, the same context is imported. It is important to note how the component fetches the corresponding context. There are two ways to do this
- ContextType is used to attach a Context object to the component. This. Context is used to retrieve the corresponding value. (In this way, components can only subscribe to a single context.)
class Demo extends React.Component {
static contextType = NavContext;
}
Copy the code
- Using context.consumer, pay attention to this API. Children needs to pass in a function that takes the value of the context
return <NavContext.Consumer>{this.renderDOM}</NavContext.Consumer>;
Copy the code
With this approach, the pass value needs to be used directly in the DOM, and if it needs to be used in a component method, the corresponding value needs to be bound to the component instance.
renderDOM = ({ handleNavChange }) = > {
this.handleNavChange = handleNavChange;
Copy the code
Use the Tips
- Using the Context component to update the Context, you can configure a callback method in the Context object to call the method within the component to update the Context
<NavContext.Provider value={{ color: this.state.color.setColor: (color) = > this.setState({ color }) }}>
</NavContext.Provider>
Copy the code
In fact, the official documentation is quite clear. On the link to pay
GetParams and setParams
This code is ok. Post it
/** * gets the url parameter */
const getParams = (function(_global) {
return function(name) {
const reg = new RegExp(` (^ | &)${name}) = (/ ^ & * (& | $) `.'i');
let result = [];
if(_global.location.hash ! = =' ') {
result = _global.location.hash.split('? '); // prioritize hash
} else {
result = _global.location.href.split('? ');
}
if (result.length === 1) {
result = _global.parent.location.hash.split('? ');
}
if (result.length > 1) {
const r = result[1].match(reg);
if(r ! =null) {
return decodeURIComponent(r[2]); }}return null;
};
})(global);
/** * Set parameters */
const setParams = (function(global) {
let _global = global;
const _originHref = _global.location.href.split(The '#') [0];
return function(name, value) {
if(! name) {return;
}
let obj = {};
if (typeof name === 'string') {
obj = {
[name]: value,
};
}
if (Object.prototype.toString.call(name) === '[object Object]') {
obj = name;
}
let hashArr = [];
if (_global.location.hash) {
hashArr = _global.location.hash.split('? ');
}
const paramArr = (hashArr[1] && hashArr[1].split('&')) || [];
let paramObj = {};
paramArr.forEach(val= > {
const tmpArr = val.split('=');
paramObj[tmpArr[0]] = decodeURIComponent(tmpArr[1] | |' ');
});
paramObj = Object.assign({}, paramObj, obj);
const resArr =
Object.keys(paramObj).map(key= > `${key}=The ${encodeURIComponent(paramObj[key] || ' ')}`) | | []; hashArr[1] = resArr.join('&');
const hashStr = hashArr.join('? ');
if (_global.history.replaceState) {
const url = _originHref + hashStr;
_global.history.replaceState(null.' ', url);
} else{ _global.location.hash = hashStr; }}; })(global);Copy the code