这被认为是来自高阶组件的变异吗?

时间:2017-12-28 03:31:31

标签: reactjs higher-order-components object-composition

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

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())。那么使用抽象方法继承可能更适合我想做的事情吗?

1 个答案:

答案 0 :(得分:1)

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

也许这样的事情。

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