我来自angular世界,在那里我可以提取逻辑到服务/工厂,并在我的控制器中使用它们。

我试图了解如何在React应用程序中实现相同的功能。

假设我有一个验证用户密码输入的组件(它的强度)。它的逻辑相当复杂,因此我不想把它写在组件中。

我应该把这个逻辑写在哪里?如果我在商店里使用助焊剂?还是有更好的选择?


当前回答

请记住,React的目的是更好地耦合逻辑上应该耦合的东西。如果您正在设计一个复杂的“验证密码”方法,它应该耦合在哪里?

每次用户需要输入新密码时,你都需要用到它。这可能出现在注册屏幕、“忘记密码”屏幕、管理员“为其他用户重置密码”屏幕等。

但在这些情况下,它总是会绑定到某个文本输入域。这就是它们应该耦合的地方。

制作一个非常小的React组件,只包含一个输入字段和相关的验证逻辑。在所有可能需要密码输入的表单中输入该组件。

这本质上与为逻辑提供服务/工厂的结果相同,但您将其直接耦合到输入。因此,现在您永远不需要告诉该函数在哪里查找它的验证输入,因为它是永久地绑定在一起的。

其他回答

在React世界中,我们有两种类型的逻辑:有状态的和无状态的。现在,这是开始React时要掌握的主要概念。这里我们更新的状态应该是更新UI,而不是Angular对dom的直接更新。两种类型的逻辑是:

That do not depend on state changes, i.e. static logic which doesn't need to re-render something based on state changes. For such cases just create regular js files and import them like a library or helper methods If you have some code that depends on state and u need to resuse it then two options - hocs and the newer hooks. Hooks are a bit hard to wrap our heads around but basically they would force their parent to rerender if their internal state changes so any stateful logic can be defined and reused in different components, and each hook instance would have its own isolated scope.

理解状态和声明性组件需要一点思维转变,但可以在评论中随意提出后续问题

我和你处境相同。在你提到的情况下,我将输入验证UI组件实现为一个React组件。

我同意验证逻辑本身的实现应该(必须)不耦合。因此,我会把它放在一个单独的JS模块中。

也就是说,对于不应该耦合的逻辑,在单独的文件中使用JS模块/类,并使用require/import将组件与“服务”解耦。

这允许独立地进行依赖注入和单元测试。

我需要一些可以在多个组件间共享的格式化逻辑,而作为Angular开发人员,我自然也倾向于使用服务。

我通过将其放在一个单独的文件中来共享逻辑

function format(input) {
    //convert input to output
    return output;
}

module.exports = {
    format: format
};

然后把它作为一个模块导入

import formatter from '../services/formatter.service';

//then in component

    render() {

        return formatter.format(this.props.data);
    }

我也来自Angular.js领域,React.js中的服务和工厂更简单。

你可以像我一样使用普通的函数或类,回调样式和事件Mobx:)

// Here we have Service class > dont forget that in JS class is Function class HttpService { constructor() { this.data = "Hello data from HttpService"; this.getData = this.getData.bind(this); } getData() { return this.data; } } // Making Instance of class > it's object now const http = new HttpService(); // Here is React Class extended By React class ReactApp extends React.Component { state = { data: "" }; componentDidMount() { const data = http.getData(); this.setState({ data: data }); } render() { return <div>{this.state.data}</div>; } } ReactDOM.render(<ReactApp />, document.getElementById("root")); <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>JS Bin</title> </head> <body> <div id="root"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> </body> </html>

这里有一个简单的例子:

可以使用export关键字从包含必要方法的文件中使用函数。

让我举个例子。假设我们有一个名为someservices .ts的文件:

export const foo = (formId: string) => {
    // ... the code is omitted for the brevity
}


export const bar = (): Entity[] => [
    // ... the code is omitted for the brevity
]

export default {
    foo,
    bar,
}

然后我们可以像这样在组件中使用这个服务:

import {
    foo,
    bar,
} from './someService'

const InnerOrderModal: FC = observer(() => {
    const handleFormClick = (value: unknown, item: any) => {
    foo(item.key)
    bar()
    
    return <></>
}