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
);
当单击ChangeNumber按钮控制台时显示
rendering app
Rerendering wrapper Component
Rerendering Number Component
Rerendering wrapper Component
Rerendering Text Component
以及数字和文本的背景颜色都会改变。
反应上下文应该仅将提供者的消费者重新呈现,对吗?为什么要重新提供提供者的所有子代?
我希望只有数字更改才能使数字和文本的背景色保持相同,并且在单击更改数字按钮后从控制台输出以下,因为应该仅让使用者重新呈现文本和数字组件。
rendering app
我想念什么?
我从sandbox中获取了代码
WrappedNumber
和WrappedText
会在您更新App组件中的状态时重新呈现,因为在虚拟DOM中它们与提供者位于同一层次结构中,并且当父组件更新时,子组件也会被更新。
为了避免它们重新呈现,您可以将它们作为App的子类提供
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
);