如果没有可用的数据,我已经创建了更高阶的组件来渲染加载器。名为 Loader 的组件是高阶组件。而名为 ContactList 的组件将调用“高级”组件。 我的ContactList组件代码:
import React, { Component } from 'react';
import '../App.css';
import Loader from './hoc/Loader.js';
class ContactList extends Component {
constructor(props) {
super(props);
this.state = {
}
}
render() {
return (
<div className="App">
{
this.props.contacts.map((contact, index) => (
<div key={index}>
<p>{contact.name}</p>
</div>
))
}
</div>
);
}
}
export default Loader(this.props.contacts)(ContactList);
Loader(HOC)组件的代码-
import React, { Component } from 'react';
import './Loader.css';
const Loader = (propName) => (WrappedComponent) => {
return class Loader extends Component {
isEmpty(prop) {
return (
prop === null ||
prop === undefined ||
(prop.hasOwnProperty('length') && prop.length === 0) ||
(prop.constructor === Object.keys(prop).length === 0)
);
}
render() {
return this.isEmpty(propName) ? <div className="loader"></div> : <WrappedComponent {...this.props}/>
}
}
}
export default Loader;
但是我收到此错误
未捕获的TypeError:无法读取未定义的属性“联系人” 因为道具在课外无法访问。
我尝试了许多解决方案-
2)如果我将导出语句更改为export default Loader(ContactList)
,则可以正常工作,但加载器组件不再可重用
答案 0 :(得分:1)
这里:
export default Loader(this.props.contacts)(ContactList);
您正在尝试在课外使用道具。无法从ContactList类中访问它们。
编辑
如果您需要显示加载程序,则取决于联系人数组,则无需使用HOC。只需在模板内部使用Loader:
<Loader contacts={this.props.contacts}>
{
this.props.contacts.map((contact, index) => (
<div key={index}>
<p>{contact.name}</p>
</div>
))
}
</Loader>
注意,在这种情况下,您必须使Loader只是一个组件,而不是HOC 。
以下是这种情况的示例:
class Loader extends React.Component {
render(){
const {values} = this.props;
if (values.length) {
return this.props.children;
}
return <div>Loading...</div>
}
}
并在ContactListComponent中使用它:
import React, { Component } from 'react';
import '../App.css';
import Loader from './hoc/Loader.js';
class ContactList extends Component {
constructor(props) {
super(props);
this.state = {
}
}
render() {
return (
<div className="App">
<Loader values={this.props.contacts}>
{
this.props.contacts.map((contact, index) => (
<div key={index}>
<p>{contact.name}</p>
</div>
))
}
</Loader>
</div>
);
}
}
export default ContactList;
Loader组件只是示例,请使用您自己的Loader。 就像我说过的那样,无需使用HOC。无论如何,您的Loader组件将是可重用的,因为您也可以在其他组件中使用它。希望这会有所帮助
答案 1 :(得分:0)
问题似乎是您尝试访问道具的方式:
export default Loader(this.props.contacts /* <-- this is incorrect */ )(ContactList);
重新考虑情况-您要达到的目标是什么? this
在模块上下文中是什么意思?
通常,在使用HOC时,您会发现出现类似的模式:
export default Loader(ContactList);
然后(取决于Loader
的实现)将允许您导入该组件(即LoaderContactList)并将道具“穿过” Loader
向下传递到内部ContactList
,如下所示:
<LoaderContactList contacts={ [ 'bob', 'joe', 'mary' ] } />
希望这可以提供一些澄清。
要说明我的答案中描述的HOC概念,请参阅以下内容:
export function(InnerComponent) { // This is the higher-order-function to export (ie Loader)
return class OuterComponent extends Component { // This is the higer-order-component
render() {
/* To illustrate the possiblitiy of reusable code via HOC's,
this HOC responds to an generic 'isBusy' prop by returning
a loading message if truthy */
if(this.props.isBusy) {
return <p>Loading</p>
}
/*
Otherwise, the inner component that you pass to the higer-
order-function is rendered. The "pass through" concept I
discuss is shown here. Notice how all props from the
OuterComponent are passed through to the InnerComponent (ie
ContactList)
*/
return <InnerComponent { ...this.props } />
}
}
}
答案 2 :(得分:0)
导出默认的加载程序(this.props.contacts)(ContactList);
这是错误的,您必须在类的外部设置一个let变量并将其设置在类的内部,然后在其中调用
答案 3 :(得分:0)
您的代码应如下所示
HOC:
const Loader = (props) => (WrappedComponent) => (moreProps) => {
const ContactList = props.ContactList;
return (
<Wrapper>
<Container>
<WrappedComponent {...moreProps} />
</Container>
</Wrapper>
)
}
现在您可以像这样使用它
export default Loader({ [ 'Praveen', 'Hari', 'Swamy' ] })(ContactList)
答案 4 :(得分:0)
我更改了传递和访问数据的方式。我更改的代码如下-
ContactList组件的代码
import React, { Component } from 'react';
import '../App.css';
import Loader from './hoc/Loader.js';
class ContactList extends Component {
constructor(props) {
super(props);
this.state = {
}
}
render() {
return (
<div className="App">
{
this.props.contacts.map((contact, index) => (
<div key={index}>
<p>{contact.name}</p>
</div>
))
}
</div>
);
}
}
export default Loader('contacts')(ContactList);
加载程序的代码(高级组件)-
import React, { Component } from 'react';
import './Loader.css';
const Loader = (propName) => (WrappedComponent) => {
return class Loader extends Component {
isEmpty(prop) {
return (
prop === null ||
prop === undefined ||
(prop.hasOwnProperty('length') && prop.length === 0) ||
(prop.constructor === Object.keys(prop).length === 0)
);
}
render() {
return this.isEmpty(this.props[propName]) ? <div className="loader"></div> : <WrappedComponent {...this.props}/>
}
}
}
export default Loader;