如何在React中包装渲染函数?

时间:2017-02-02 03:18:11

标签: reactjs ecmascript-6

我已经在ES5中包装了渲染函数,如:

var Test = React.createClass({
  componentDidUpdate:function()
    {
       this.refs.table.cleanSelected();

    },
    getInitialState: function() {
        return getItemPropertyData();
    },
   render:ExceptionInterceptor('Test','render',function(){
      return(
       <h1>Test</h1>
       )
    })
});

我的ExceptionInterceptor组件看起来像

 var ExceptionInterceptor = function (fileName, functionName, renderFunction, component) {
    return function () {
        try {
            return renderFunction.apply(this, arguments);
        }
        catch (e) {
          console.log(e);
        }
    }
};

现在我想在ES6组件渲染方法中应用相同的包装,如

export default class Test extends React.Component {
    componentDidUpdate()
    {
       this.refs.table.cleanSelected();

    }
    getInitialState()
    {
        return getItemPropertyData();
    }
    render()
    {
    return(
      <h1>Test<h1>
     )
    }
}

如何在上面提到的es6代码中用ExceptionInterceptor包装render方法?

2 个答案:

答案 0 :(得分:2)

由于你使用的是Interceptor,在ES6中实现它的最好方法是DECORATOR @ExceptionInterceptor:你不需要传递类名和方法名,因为它是由装饰器自动检测的:

文件:/src/Decorators.js

export function ExceptionInterceptor(target, key, descriptor) {

  // console.log(target, key, descriptor) --> try this line if you want to know what decorator detects when it is applied .
   const realFunction = descriptor.value; // which is "render" in your example 

   // Now intercept the realFuntion by overriding `descriptor.value`
   descriptor.value = function() {
    try {
       return realFunction.apply(this, arguments);
    } catch(e) {
       console.log(e);
    }  


  };
  return descriptor;
}

然后:

文件:/src/Test.jsx

import {ExceptionInterceptor} from './Decorators.js'; 

export default class Test extends React.Component {
    componentDidUpdate()
    {
       this.refs.table.cleanSelected();

    }
    getInitialState()
    {
        return getItemPropertyData();
    }

   @ExceptionInterceptor 
    render()
    {
      return (
        <h1>Test<h1>
      )
    }
}

检查您的.babelrc配置文件;它必须包含:

  • stage-1或更高,作为其中一个“

  • 装饰器插件的插件:transform-decorators-legacysyntax-decorators

无论如何,我使用以下配置.babelrc

{
    "presets": ["es2015", "stage-3", "react"],
    "env": {},
    "plugins": [
        "transform-decorators-legacy",
        "react-html-attrs",
        "syntax-decorators",
        "transform-es2015-modules-commonjs",
        ["transform-class-properties", { "spec": true }]
    ]
}

答案 1 :(得分:2)

我是同一个提供装饰器解决方案的人,然而,很难配置项目来接受装饰器,这就是为什么我现在会给出一个可以工作ISA的解决方案,但是,它不像装饰者的解决方案那样优雅:

render()&amp;中删除Test方法在Test课程之后添加如下:

Test.prototype.render = ExceptionInterceptor('Test','render',function(){
      return(
       <h1>Test</h1>
       )
    });

这不会修改ExceptionInterceptor,而是使它与两个ES兼容。

课程的整个文件将是:

 class Test extends React.Component {

    constructor() {
      super(...arguments);
      this.state = getItemPropertyData();
    }

    componentDidUpdate()
    {
       this.refs.table.cleanSelected();
    }

}

Test.prototype.render = ExceptionInterceptor('Test','render',function(){
      return (
         <h1>Test</h1>
       )
 });

export default Test // export it in the last line (remove export from the beginning of class)