【问题标题】:Is it an anti-pattern to use variables the outside of React function component?在 React 函数组件的外部使用变量是一种反模式吗?
【发布时间】:2021-08-04 03:20:27
【问题描述】:

下面的情况是 React 中的反模式吗?

由于某些原因,变量和函数可能会在 React 函数组件之外声明。例如,定时器 ID 等可以如下使用:

import React from "react";

const myFunc = () => { // no purpose
    /*some codes*/
}
let myBool = false; // no purpose
let timerId = 0;
    
const MyComponent = () => {
    const [name, setName] = useState("");
    
    /* some codes */

    useEffect(() => {
        timerId = setTimeout(() => {
            /* some codes */
        }, 1000);
            
        return () => clearTimeout(timerId);
    }, []);
        
    return (
        <div>Hello world</div>
    );
}

export default MyComponent;

【问题讨论】:

  • 你的例子中myBoolmyFunc的目的是什么?
  • @ksav 我把它们当作没有目的的傻瓜。
  • 为什么要添加无用的变量?
  • @ksav 很抱歉造成混乱。我应该排除那些。

标签: reactjs anti-patterns


【解决方案1】:

这样做不是犯罪。但在你这样做之前,想想你为什么要这样做。

如果您想像export { MyComponent, myFunc, timerId, myBool}; 这样将这些变量与组件一起暴露给外部世界,那么使用这种模式是有意义的。否则最好在函数式组件内部声明变量/函数。

是的,它是一种反模式。 IMO 功能组件背后的整个想法是使组件变得纯净。使反应功能组件纯粹,使其更可预测,您的输出仅由函数的输入决定。在函数范围之外使用变量会使函数不再纯。使用纯函数有几个好处。我强烈推荐使用纯功能组件。

https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-pure-function-d1c076bec976

【讨论】:

    【解决方案2】:

    对于可能更改的变量,例如在您的示例中,是的,这很可能被认为是一个问题,因为您无法指望使用具有一致的效果,因为它不是纯粹的,而是取决于外部变量的当前状态(而不是 React 状态)。

    例如,如果您有一个MyComponent,并且您后来决定在您的站点中添加另一个也使用MyComponent 的部分,并且两者都同时呈现,那么您现有的代码会导致问题,因为这两个组件将共享相同的 timerId 变量 - 第一个要渲染的组件将丢失其 timerId。 (只有要渲染的第二个组件才能清除持久的外部timerId

    在这些情况下,组件内使用的值与该组件的给定实例有关,而不是整个应用程序,您应该使用状态(使用useState)而不是一个外部变量。

    不过,通常使用外部标识符并不总是一个坏主意 - 恰恰相反,对于不会改变且抽象出来有用的常量值,例如 URL、API 密钥、单独的非 React 函数, 等等。以下类型的模式并不少见:

    import { makeApiCall } from './makeApiCall';
    
    export const SomeComponent = () => {
      // ...more code here dealing with state
      const handleClick = () => {
        makeApiCall()
          .then(handleSuccess)
          .then(handleFail);
      };
      return (
        <button onClick={handleClick}>click</button>
      );
    };
    

    【讨论】:

      【解决方案3】:

      是的,它被视为反模式,您不能只在组件内定义这些变量,因为该值将在重新渲染组件时重新初始化。 我们在 react 中有 ref 对象来实现这一点:

      import React from "react";
      
      const myFunc = () => { // no purpose
          /*some codes*/
      }
          
      const MyComponent = () => {
          const [name, setName] = useState("");
          const myBool = useRef(false);
          const timerId = useRef(0);
          
          /* some codes */
      
          useEffect(() => {
              timerId.current = setTimeout(() => {
                  /* some codes */
              }, 1000);
                  
              return () => clearTimeout(timerId.current);
          }, []);
              
          return (
              <div>Hello world</div>
          );
      }
      
      export default MyComponent;
      

      myBooltimerId 在重新渲染时不会改变,您可以根据需要改变这些对象。你可以阅读更多here

      【讨论】:

      • 感谢您的回答。使用 ref 似乎比使用外部变量要好得多。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-20
      • 2017-08-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多