Reactjs UI 和业务逻辑分离

sab*_*nan 49 javascript separation-of-concerns reactjs react-hooks

我是 React 新手,看到充满大量函数和变量初始化以及 UI 的组件,我觉得眼睛很痛。有可能将它们分开吗?

而不是默认设置,如下所示。如何将业务逻辑分离到另一个文件中?

function MyComponent() {
    const [data, setData] = useState('');
    const someFunc = () => {
        //do something.
    };
    ... some 100-liner initializations

   return ( 
       ...
   )
}
Run Code Online (Sandbox Code Playgroud)

小智 89

是的,这是可能的,这就是所谓的Separation of concern

您可以如下创建组件结构。

MyComponentDirectory
 - useCustomHook
 - Component
 - helper
Run Code Online (Sandbox Code Playgroud)

代码看起来像这样。

const useCustomHook = () => {

    const [value, setValue] = useState('');
    const handleClick = (value) => {
        setValue(value)
        //do something.
    };
    ... some 100-liner initializations/business logic, states, api calls. 

    return {
        value, 
        handleClick,
        ... // Other exports you need. 
    } 
}

export default useCustomHook; 
Run Code Online (Sandbox Code Playgroud)

成分

function MyComponent() {
   const {
       value, 
       handleClick, 
       ... // Other imports 
   } = useCustomHook() 

   return ( 
       <Element value={value} onClick={handleClick} />
   )
}

Run Code Online (Sandbox Code Playgroud)

帮手

const doSomething = () => {}
Run Code Online (Sandbox Code Playgroud)

编辑

这是使用 React 计数器应用程序的详细示例Separation of concern

结构

Directory
- App
- Counter
- useCounter
- helper
Run Code Online (Sandbox Code Playgroud)

应用程序组件

MyComponentDirectory
 - useCustomHook
 - Component
 - helper
Run Code Online (Sandbox Code Playgroud)

计数器组件

const useCustomHook = () => {

    const [value, setValue] = useState('');
    const handleClick = (value) => {
        setValue(value)
        //do something.
    };
    ... some 100-liner initializations/business logic, states, api calls. 

    return {
        value, 
        handleClick,
        ... // Other exports you need. 
    } 
}

export default useCustomHook; 
Run Code Online (Sandbox Code Playgroud)

使用反钩

function MyComponent() {
   const {
       value, 
       handleClick, 
       ... // Other imports 
   } = useCustomHook() 

   return ( 
       <Element value={value} onClick={handleClick} />
   )
}

Run Code Online (Sandbox Code Playgroud)

辅助功能

const doSomething = () => {}
Run Code Online (Sandbox Code Playgroud)

这是Codesandbox中的工作示例

注意:如果您创建一个简单的 Javascript util 函数而不是钩子,那么您将无法访问其他钩子以及该函数内的上下文。

  • 这是一个了不起的例子!经过进一步思考,我们可以将 `numberWithCommas(..)` 方法从自定义钩子中移出,并直接在 ui 中调用 `&lt;p&gt;{numberWithCommas(count)}&lt;/p&gt;` 这样我们的自定义钩子就充当了隔离模型(数据)没有任何视图逻辑。它所需要做的就是保留状态、更新并通知侦听器 (UI)。这使得它更加可重复使用和清洁。只是一个想法 :) (3认同)
  • 在 Angular 工作多年后学习 React,将所有渲染和组件逻辑放在一个地方,并且将 html(jsx) 放在大量业务逻辑之下,这确实令人沮丧。这正是我一直在寻找的。我认为这应该是默认约定,即每个组件都应该有一个用于业务逻辑的钩子,以保持 UI 组件的精简。 (2认同)

小智 5

我自己使用的一种常见方法是将业务逻辑分离到自己的文件中myComponentHelper.js

这也将使测试函数变得更容易,因为如果不将其作为参数传递并返回更改,它将无法使用和更改反应状态。

myComponent/
  myComponent.jsx
  myComponentHelper.js
  myComponentTest.js
Run Code Online (Sandbox Code Playgroud)
myComponent/
  myComponent.jsx
  myComponentHelper.js
  myComponentTest.js
Run Code Online (Sandbox Code Playgroud)
// myComponent.js

import { someFunc } from './myComponentHelper';

function MyComponent() {
    const [data, setData] = useState('');
    
    const x = someFunc(data);

    return ( 
        ...
    )
}
Run Code Online (Sandbox Code Playgroud)
// myComponentHelper.js

export const someFunc = (data) => {
    //do something.
    return something;
}
Run Code Online (Sandbox Code Playgroud)