这是否被认为是来自高阶组件的突变?

Is this considered mutation from a Higher Order Component?

我正在阅读有关 不要改变原始组件的部分。使用 link.

中的 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 的答案是肯定的,那么我可能需要更好的设计 pattern/approach 来完成我在代码中尝试描述的内容。这基本上是我的大部分组件需要获取自己的数据 (Home.fetchAllData(){then set the state()}),更新视图 (Home.render()),运行 一些通用动画函数 (Wrapper.componentWillAppear(){this.animateFunctionOfSomeKind()}),然后 运行 特定于自身的动画 (Home.animateContent())。所以也许用抽象方法继承更适合我想做的事情?

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

也许是这样的。

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(只是一个函数),它接受一个异步函数和 returns 另一个接受一个组件的函数。它将调用该函数并将第一个和第二个结果分配给 state,然后将其作为 props 传递给包装的组件。它遵循本文的原则:https://medium.com/@franleplant/react-higher-order-components-in-depth-cf9032ee6c3e