我正在尝试使用ES6语法构建一个ReactJS高阶组件。这是我的尝试:
export const withContext = Component =>
class AppContextComponent extends React.Component {
render() {
return (
<AppContextLoader>
<AppContext.Consumer>
{context => <Component {...props} context={context} />}
</AppContext.Consumer>
</AppContextLoader>
);
}
};
这里,AppContextLoader
从数据库获取上下文并将其提供给上下文,如:
class AppContextLoader extends Component {
state = {
user: null,
};
componentWillMount = () => {
let user = databaseProvider.getUserInfo();
this.setState({
user: user
});
};
render = () => {
return (
<AppContext.Provider value={this.state}>
{this.props.children}
</AppContext.Provider>
);
};
}
export default AppContextLoader;
用法:
class App extends Component {
static propTypes = {
title: PropTypes.string,
module: PropTypes.string
}
render = () => {
return (
withContext(
<Dashboard
module={this.props.module}
title={this.props.title}
/>
);
export default App;
由于某些原因,我的包裹组件(Dashboard
)没有获得context
属性,只有原始属性(title
和module
)。
如何使用ES6语法正确编写HOC?
答案 0 :(得分:1)
您没有正确使用HOC,您需要传递组件而不是组件实例。从render中调用HOC也是一个糟糕的模式,因为每次渲染都会返回一个新组件,你必须写
const DashboardWithContext = withContext(Dashboard);
class App extends Component {
render = () => {
return (
<DashboardWithContext
module={"ADMIN"}
title={"MY APP"}
/>
)
}
}
export default App;
同样在withContext HOC
中,因为返回的组件是一个类,您将访问类似{...this.props}
而不是{...props}
的道具。但是,因为您不是,所以使用功能组件是有意义的实际上使用生命周期方法
export const withContext = Component => (props) => (
<AppContext.Consumer>
{context => <Component {...props} context={context} />}
</AppContext.Consumer>
);
<强> Working Codesandbox 强>
答案 1 :(得分:0)
应改为this.props
:
<Component {...this.props}
这应该适合你:
render() {
const props = this.props;
return (
<AppContext.Consumer>
{context => <Component {...props} context={context} />}
</AppContext.Consumer>
);
}
答案 2 :(得分:0)
您遇到一些问题:
您没有正确使用Context API-创建上下文是为了使用Provider
与一个或多个Consumers
共享一个值-您是通过即席创建的新的Provider
和Consumer
。
在您的示例中,您无需使用Context
-将临时用途用于新使用数据-withUserData
您应该使用this.props
而不是道具
在用法部分,将元素而不是组件传递给hoc
您没有从withContext
解决方案
export const withUserData = BaseComponent =>
class AppContextLoader extends Component {
state = {
user: null,
};
componentWillMount = () => {
let user = databaseProvider.getUserInfo();
this.setState({
user: user
});
};
render = () => {
return (
<BaseComponent {...this.props} {...this.state} />
);
};
}
和用法:
class App extends Component {
static propTypes = {
title: PropTypes.string,
module: PropTypes.string
}
render = () => {
return (
<EnhancedDashboard
module={this.props.module}
title={this.props.title}
/>
);
}
const EnhancedDashboard = withUserData(Dashboard)
export default App;