停止在每次渲染时调用该函数

时间:2019-08-09 04:18:44

标签: javascript reactjs

在我的React.JS应用程序中,我有一个功能组件内部的函数,该函数呈现应用程序最初加载时所需的JSX。问题是我不需要每次组件更新和调用{ color: '#A5E1D2', data: [3, 3, 2, 3, 3, 6, 3] },{ color: '#A5E1D2', data: [0, 0, 0, 0, 0, 0, 0] },{ id: 'transparent', color: 'rgba(255,255,255,0)', data: [27,25,16,13,9,17,11] }] }, function(chart){ chart.get('transparent').area.hide(); }); 方法时都重新运行它。此内容是通过API调用呈现的,因此不断重新运行是“昂贵的”。

如何限制运行频率。

return()

下面是被调用的函数:

...

<Col lg="8">
    <div className="tab-content" id="newForm-wrapper">
        {/* !! STOP THIS FROM BEING CALLED EVERY RENDER !!! */}
        {renderSectionContent(formJSON)}
    </div>
</Col>

...

3 个答案:

答案 0 :(得分:3)

为防止此函数在每个渲染器上运行,您将需要在本地状态下存储该函数的返回值。您可能希望每次json数据更改时都重新运行该函数,如果json具有深度嵌套的数据,则可能会很困难。取决于您将json注入组件的方式将完全改变状态的设置方式。

下面是一个示例,该示例假定将数据作为道具传递到您的类组件,该操作将完成:

export default class MyComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      sectionContent: renderSectionContent(props.formJson),
    };
  }

  renderSectionContent = json => {
    // do stuff
    return <FormSection />;
  }

  render() {
    return (
      <Col lg="8">
        <div className="tab-content" id="newForm-wrapper">
          {this.state.sectionContent}
        </div>
      </Col>
    );
  }
}

或使用Hooks(React 16.8版中的新功能):

export default function MyComponent(props) {
  const [sectionContent, setSectionContent] = useState(renderSectionContent(props.formJson));

  const renderSectionContent = json => {
    // do stuff
    return <FormSection />;
  }

  return (
    <Col lg="8">
      <div className="tab-content" id="newForm-wrapper">
        {this.state.sectionContent}
      </div>
    </Col>
  );
}

答案 1 :(得分:1)

假设您对函数的json输入要么作为prop传递给组件,要么处于状态(如果不是,则可以将其存储在状态中?):

您可以在此处使用的两个选项中的两个是要么使该函数成为其自己的组件,然后根据条件返回所需的组件;这样,您可以将json作为道具传递,并且只有在道具更改时它才会再次运行。或者,您可以使用react reselect library中的createSelector,在其中将json保持状态(或在下面的示例中将state替换为props),然后将state或prop传递给函数(这将现在是重新选择功能)。这样,只有当您的json状态或道具更改时,您的函数才会再次运行

示例

import { createSelector } from 'reselect'

static renderSectionContent = createSelector(
    (state) => state.json,
    (json) => {
        if (json.hasOwnProperty("form") && 
            json.form.hasOwnProperty("sections")) {
                return json.form.sections.map((section, i) => {
                    return <FormSection key={i} json={section} />;
                });
        } else {
            return <FormSection json={{}}/>;
        }
    }
)


render() {
    let selectionContent = this.renderSectionContent(this.state)


    ..

    <Col lg="8">
        <div className="tab-content" id="newForm-wrapper">
            {selectionContent}
        </div>
    </Col>

   ...
}

每次调用createSelector时,它将返回该函数先前计算出的返回值,除非createSelector函数的输入之一更改

答案 2 :(得分:0)

  

使用IIFE来缓存您的JSX。

在这种情况下,最好的解决方案是使用Class组件而不是Functional。但是,即使您出于任何原因都不愿意使用这些功能,IIFE仍然是您的选择之一。怎么做?检查以下代码。

import React from 'react'
...
...

export default (function () {
  let cachedJSONString = ''
  let cachedSectionContent = null

  const renderCachedSectionContent = json => {
    let newJSONstring = JSON.stringify(json)

    if (cachedJSONString) {
      if (cachedJSONString !== newJSONstring) {
         cachedJSONString = newJSONstring
         return renderSectionContent(json)
      } else {
         return cachedSectionContent
      }
    }

    cachedJSONString = newJSONstring
    cachedSectionContent = renderSectionContent(json)

    return cachedSectionContent
  }

  const renderSectionContent = json => {
   if (json.hasOwnProperty("form") && json.form.hasOwnProperty("sections")) {
       return json.form.sections.map((section, i) => {
         return <FormSection key={i} json={section} />;
       })
    } else {
       return <FormSection json={{}}/>;
    }
  }

  return (props) => {
    return (
      ...
       <Col lg="8">
          <div className="tab-content" id="newForm-wrapper">
             {renderCachedSectionContent(props.formJSON)}
          </div>
       </Col>
      ...
    )
  }
})();

问。但是,为什么选择IIFE?

A。avoid cluttering global Namespace