就我所知,Reaction中通常/推荐的方法是设置状态并将其与setter一起传递给组件,例如

const [name, setName] = useState("");
return <>{/* stuff */} <MyStringInput value={name} setValue={setName} </>;

我觉得很奇怪,我们有这个setName函数,而我们实际上并不想在这个作用域中手动使用它,而且,MyStringInput假设setValuevalue的设置器,但这不是强制的.我认为这样的事情会更好:

const [name, nameInput] = myStringInput("");
return <>{/* stuff */} {nameInput} </>;

但是阅读Reaction上的material ,似乎应该有一个不返回JSX的钩子,或者一个只返回JSX的组件.第二种方法的缺陷是什么?

推荐答案

钩子是composing behaviour and state的一种方式,而JSX/组件本质上是应用程序的更高级别的宏视图.

它有助于理解react 本身的进程,从而了解你所描述的模式最初产生的原因.乍一看,您实际上可能认为较旧的类组件在描述您想要做的事情时更简洁,但它们本身也不太灵活.

在钩子出现之前,您已经有了类组件.在类组件中,组件本身是用于状态、效果(也称为生命周期)和表示的抽象.所有这些都倾向于结合在一个单元中.固有地将生命周期/状态与组件耦合的问题在于,生命周期和状态本质上耦合到表示层,因此逻辑在应用程序的其他地方变得更难重用.您可能经常会发现,虽然状态的范围现在只对JSX的一小部分有用,但后来,随着应用程序的增长,您会发现其他一些东西需要访问它,您需要移动状态(及其关联的生命周期行为).

出现了许多模式,在类组件上解决了这个问题,比如HOC和渲染props (值得搜索一下这些),但这些模式有不受欢迎的API,而且有些模式有根本的缺陷,使得组合行为比现在使用钩子时更笨拙.不是说它们不好,实际上它们在特定情况下仍然经常有一席之地,特别是渲染props .

类组件的另一个方面是,用于访问类组件的生命周期的API往往意味着,最终,围绕组件有多个功能需求拆分,而它们实际上应该按用途/功能进行分组.钩子使消费者能够挑选他们想要在一个整洁的重用单元中使用的库功能的哪一部分.

此外,将钩子分开意味着消费者更容易……将某个库的逻辑挂接到他们 Select 的表示风格/JSX树中,而不会固有地与其他人的样式/JSX树相关联.表单库就是一个很好的例子(请参阅Reaction-Hook-Form).

这就产生了钩子.简而言之,钩子的意思是:

  • 随着您的应用程序变得更大、更复杂,重用和移动状态和该状态的行为就变得更容易.
  • 挂钩使得真正专注于一个功能领域的重用单元变得更容易.

在使用您的示例时,虽然您可能认为nowNothing需要访问钩子的作用域,但如果这个假设是被加入的(就像类组件一样),那么当您决定新的does实际上需要该状态时,重构并在稍后拆分真的很烦人.钩子确保状态和行为保持可移植和可组合.但是,如果这段代码的级别是application,那么实际上可以从useful开始进行这些假设,并创建将它们耦合在一起的包装器.如果您不是在许多未知的上下文中创作高度可重用的东西,那么这个假设通常是安全的.

如果您确信消费者永远不会孤立地关心钩子的作用域,那么真正的答案就是简单地创建一个组件,该组件包装钩子和内部组件,该组件is是API.然而,在库中,这有时可能是一个大错误,因为如果用户的用户区域中潜在的"更高"的其他东西需要访问该状态,库用户基本上是被困住的,除非他们使用肮脏的复制技巧,这会固有地增加应用程序中的错误的表面积.

也就是说,许多库将公开易于使用的组件包装器,这些组件包装器保持内部组件的状态,并单独公开底层挂钩和内部组件,以实现易用性,同时还支持可能需要与该状态的复杂关系的高级用户,这些关系分布在他们 Select 的代码库的多个区域中.

正如我在其他地方对这个问题所做的 comments ,从钩子返回组件不是一个好主意.使用这种方法,您基本上已经在钩子中创建了一个组件(它内在地耦合了钩子和其他内部组件),而不仅仅是使用一个组件来完成这项工作.这样的钩子的行为本质上是与其表示的内部组件分不开的,类组件的问题开始重新出现.这通常会导致作用域和性能噩梦,而且很难进行推理.

Reactjs相关问答推荐

如何通过TEK查询将对象传递到Express后台

有没有方法覆盖NextJS 14中的布局?

使用Thattle和Use Effect setTimeout进行搜索有什么不同

在Reaction中测试条件组件

REACT路由DOM根据参数呈现不同的路由

防止在Reaction中卸载

在数组对象内的数组上进行映射

在Reaction中导入';图片&文件夹时出错

蚂蚁 Select .列表弹出窗口不会';有时不会出现

如何使用服务器中的数据自动填充表单字段?

React-router-dom的链接不改变路由(ReactRouter6)

React 测试库包装器组件

MUI TextField Select 菜单的最大高度

如何保留我的下一个授权用户会话?所以我可以使用提供的 ID 在其他路由中获取数据

如何使用 React 在客户端获取 nestjs websocket 异常错误?

如何通过onpress on view in react native flatlist来降低和增加特定视图的高度?

React Router v6 - 访问嵌套路由和处理手写 url 的正确方法

如何在 react-router-dom v6 中实现监听功能?

为什么 state redux-toolkit 是代理?

useEffect 仅在跟随链接后有效,不适用于直接链接