[英]How to make React HOC - High Order Components work together?
我有一個像這樣的小型演示組件:
function MyList({data, uppercaseMe, lowercaseMe}) {
return <ul>
{data.map(item =>
<li>{item} -
<button onClick={() => uppercaseMe(item)}>Uppercase me!</button>
<button onClick={() => lowercaseMe(item)}>Lowercase me!</button>
</li>)}
</ul>;
}
然后我想用三個HOC來裝飾MyList:
const WithData = (Component) => {
return class extends React.Component {
constructor(props) {
super(props);
this.state= {data:['one', 'two', 'three', 'four', 'five']};
};
render() {
return <Component {...this.props} data={this.state.data} />;
}
}
};
const WithUppercase = (Component) => {
return class extends React.Component {
uppercaseMe = (item) => {
// how to access WithData state from here?
console.log(item.toUpperCase());
};
constructor(props) {
super(props);
};
render() {
return <Component {...this.props} uppercaseMe={this.uppercaseMe}/>;
}
}
};
const WithLowercase = (Component) => {
return class extends React.Component {
lowercaseMe = (item) => {
// how to access WithData state from here?
console.log(item.toLowerCase());
};
constructor(props) {
super(props);
};
render() {
return <Component {...this.props} lowercaseMe={this.lowercaseMe}/>;
}
}
};
像這樣:
const ComposedList = WithLowercase(WithUppercase(WithData(MyList)));
不幸的是,我不知道如何在WithLowercase或WithUppercase中更改WithData的狀態。
你如何將一個HOC的狀態暴露給鏈中的另一個HOCS?
您不希望直接公開狀態。 你想要做的是將一個函數作為prop傳遞給包裝組件,以允許你更新狀態。
因此,如果我們使用HOC並添加一些代碼,則創建一個函數來更新其狀態,現在可以將其傳遞給其子組件:
const WithData = (Component) => {
return class extends React.Component {
constructor(props) {
super(props);
this.state= {data:['one', 'two', 'three', 'four', 'five']};
}
update (data) {
this.setState({ data });
}
render() {
return <Component onUpdate={this.update} {...this.props} data={this.state.data} />;
}
}
};
現在,在其中一個子組件中,我們可以使用它:
const WithUppercase = (Component) => {
return class extends React.Component {
uppercaseMe = (item) => {
const itemIndex = this.props.data.indexOf(item);
const newData = this.props.data.slice();
newData[itemIndex] = item.toUpperCase();
this.props.onUpdate(newData); // update WithData state here
};
constructor(props) {
super(props);
};
render() {
// onUpdate function is once again passed to child components
// implicitly through props if you need to call it again
return <Component {...this.props} uppercaseMe={this.uppercaseMe}/>;
}
}
};
將數據傳遞回組件鏈本質上違背了反應使用的模式,這是數據流的一種方式。 數據下降但永遠不會恢復。 就像@FuriousD所說的那樣,你應該讓lowerCase和upperCase方法可用於鏈中的組件。 您可以使用上下文執行此操作。
“在某些情況下,您希望通過組件樹傳遞數據,而不必在每個級別手動傳遞道具。您可以使用強大的”上下文“API直接在React中執行此操作。”
以下是使用代碼更新版本的示例。
const WithUpperCase = (Component) => {
class _WithUpperCase extends React.Component {
getChildContext() {
return {
uppercaseMe: this.uppercaseMe,
}
}
uppercaseMe = (item) => {
return item.toUpperCase()
};
render() {
return <Component {...this.props} />;
}
}
_WithUpperCase.childContextTypes = {
lowercaseMe: PropTypes.func,
}
return _WithUpperCase;
};
const WithLowercase = (Component) => {
class _WithLowercase extends React.Component {
getChildContext() {
return {
lowercaseMe: this.lowercaseMe,
}
}
lowercaseMe = (item) => {
return item.toLowerCase()
};
render() {
return <Component {...this.props} />;
}
}
_WithLowercase.childContextTypes = {
lowercaseMe: PropTypes.func,
}
return _WithLowercase;
};
function MyList({ data }, { uppercaseMe, lowercaseMe }) {
return (
<ul>
{
data.map(item => (
<li>{item} -
<button onClick={() => uppercaseMe(item)}>Uppercase me!</button>
<button onClick={() => lowercaseMe(item)}>Lowercase me!</button>
</li>
))
}
</ul>
);
}
MyList.contextTypes = {
// Need to import the PropTypes library
uppercaseMe: PropTypes.func,
lowercaseMe: PropTypes.func,
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.