import React, { useReducer, useEffect ,Component} from "react";
import ReactDOM from "react-dom";
const AppContext = React.createContext();
import React from "react";
const withRandomColors = WrappedComponent => {
return class RandomColors extends React.Component {
constructor() {
super();
this.randomColors = [
"red",
"blue",
"green",
"cyan",
"lavender",
"skyblue",
"orange",
"pink",
"yellow"
];
}
getRandomColors() {
const num = Math.floor(Math.random() * 10) % 9;
return this.randomColors[num];
}
render() {
console.log("Rerendering wrapper Component");
return <WrappedComponent randomColor={this.getRandomColors()} />;
}
};
};
class Number extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {}
render() {
console.log("rendering Number Component");
return (
<AppContext.Consumer>
{({ number }) => {
return (
<div style={{ backgroundColor: `${this.props.randomColor}` }}>
{number} <br />
</div>
);
}}
</AppContext.Consumer>
);
}
}
class Text extends React.Component {
constructor(props) {
super(props);
}
render() {
console.log("rendering Text Component");
return (
<AppContext.Consumer>
{({ text }) => (
<div style={{ backgroundColor: `${this.props.randomColor}` }}>
{text} <br />
</div>
)}
</AppContext.Consumer>
);
}
}
const WrappedText=withRandomColors(Text);
const WrappedNumber=withRandomColors(Number);
class App extends Component {
constructor() {
super();
this.state = {
number: Math.random() * 100,
text: "testing context api"
};
}
updateNumber = () => {
const randomNumber = Math.random() * 100;
this.setState({ number: randomNumber });
};
render() {
console.log("rendering app")
return (
<AppContext.Provider value={this.state}>
<div>
<h1>Welcome to React</h1>
<WrappedNumber />
<WrappedText />
<button onClick={this.updateNumber}>Change Number </button>
</div>
</AppContext.Provider>
);
}
}
ReactDOM.render(
<App />,
mountNode
);
when clicked on ChangeNumber button console displays
rendering app
Rerendering wrapper Component
Rerendering Number Component
Rerendering wrapper Component
Rerendering Text Component
and background color changes for both number and text.
React context is supposed to rerender only consumers for the provider right? why is it rerendering All the children of Provider?
I expected that only number changes keeping background color of Number and Text as same and below output from console once clicked on Change Number button since only consumers are supposed to rerender not the Text and Number components.
rendering app
what am I missing?
I took the code from sandbox
WrappedNumber
and WrappedText
re-render when you update a state in the App component because in the Virtual DOM they come in the same hierarchy as the Provider and when the parent component updates the child components are updated too.
To avoid them from re-rendering you could provide them as children of App like
class App extends Component {
constructor() {
super();
this.state = {
number: Math.random() * 100,
text: "testing context api"
};
}
updateNumber = () => {
const randomNumber = Math.random() * 100;
this.setState({ number: randomNumber });
};
render() {
console.log("rendering app")
return (
<AppContext.Provider value={this.state}>
<div>
<h1>Welcome to React</h1>
{this.props.children}
<button onClick={this.updateNumber}>Change Number </button>
</div>
</AppContext.Provider>
);
}
}
ReactDOM.render(
<App >
<WrappedNumber />
<WrappedText />
</App>,
mountNode
);