0

我正在阅读关于不要改变原始组件的部分。使用此链接中的组合。

https://reactjs.org/docs/higher-order-components.html

然后我回顾了一个我正在尝试构建的项目。在高层次上,这就是我的代码的样子:

class Wrapper extends Component {

    constructor(props) {
        this.wrappedComponent = props.wrappedComponent;
    }

    async componentWillAppear(cb) {
        await this.wrappedComponent.prototype.fetchAllData();

        /* use Greensock library to do some really fancy animation on the wrapper <Animated.div> */

        this.wrappedComponent.prototype.animateContent();

        cb();
    }

    render() {
        <Animated.div>
        <this.wrappedComponent {...this.props} />
        </Animated.div>
    }
}

class Home extends Component {

    async fetchAllData(){
        const [r1,r2] = await Promise.All([
            fetch('http://project-api.com/endpoint1'),
            fetch('http://project-api.com/endpoint2')
        ]);

        this.setState({r1,r2});
    }
    animateContent(){
        /* Use the GreenSock library to do fancy animation in the contents of <div id="result"> */
    }

    render() {
        if(!this.state)
            return <div>Loading...</div>;

        return (
            <div id="result">
            {this.state.r1.contentHTML}
            </div>
        );
    }

}

export default class App extends Component {
    render() {
        return <Wrapper wrappedComponent={Home} />;
    }
}

我的问题是:

  1. 在我的Wrapper.componentWillAppear()中,我触发了对象方法,例如this.wrappedComponent.prototype.<methodname>. 这些对象方法可以设置它自己的状态或在渲染函数中为 html 的内容设置动画。这是否考虑改变原始组件
  2. 如果问题 1 的答案是肯定的,那么也许我需要一种更好的设计模式/方法来完成我试图在我的代码中描述的内容。这基本上是我的大部分组件需要获取自己的数据(Home.fetchAllData(){then set the state()}),更新视图(Home.render()),运行一些通用动画函数(Wrapper.componentWillAppear(){this.animateFunctionOfSomeKind()}),然后运行特定于自身的动画(Home.animateContent())。所以也许用抽象方法继承更适合我想做的事情?
4

1 回答 1

1

我可能实际上会编写一个实际的高阶组件。而不仅仅是一个组件,它采用一个组件(这是您在示例中所做的)。主要是因为我认为您实现它的方式有点代码异味/反模式。

可能是这样的。

class MyComponent extends React.Component {
    constructor() {
        super();
        this.animateContent = this.animateContent.bind(this);
    }

  componentWillReceiveProps(nextProps) {
    if (this.props.r1 !== nextProps.r1) {
        this.animateContent();
    }
  }

    componentDidMount() {
        // do your fetching and state setting here
    }

    animateContent() {
        // do something
    }

    render() {
        if(!this.props.r1) {
            return <div>Loading...</div>;
        }

        return (
            <div id="result">
            {this.props.r1.title}
            </div>
        );
    }
}

 const myHOC = asyncFn => WrappedComponent => {
   return class EnhancedComponent extends React.Component {
     async componentDidMount(){
       const [r1, r2] = await asyncFn();
       this.setState({ r1, r2 })
       this.animateContent();
     }

     animateContent = () => {
        // do some animating for the wrapper.
     }

     render() {
       return (<WrappedComponent {...this.props} {...this.state} />)
     }
   }
 }


 const anAsyncExample = async () => {
        const result = await fetch("https://jsonplaceholder.typicode.com/posts");
    return await result.json();
 }

 const MyEnhancedComponent = myHOC(anAsyncExample)(MyComponent);

这是一个有效的 JSFiddle,因此您可以在使用中看到它: https ://jsfiddle.net/patrickgordon/69z2wepo/96520/

本质上,我在这里所做的是创建了一个 HOC(只是一个函数),它接受一个异步函数并返回另一个接受和包装组件的函数。它将调用该函数并将第一个和第二个结果分配给 state,然后将其作为 props 传递给包装的组件。它遵循本文的原则:https ://medium.com/@franleplant/react-higher-order-components-in-depth-cf9032ee6c3e

于 2017-12-28T04:55:29.597 回答