Ocaml 进行不必要的回调创建和分配(初始状态…)?

Ocaml 进行不必要的回调创建和分配(初始状态…)?,ocaml,reason,reason-react,Ocaml,Reason,Reason React,我不明白的工作方式: let component = ReasonReact.reducerComponent("Greeting"); let make = (~name, _children) => { ...component, initialState: () => 0, /* here, state is an `int` */ render: (self) => { let greeting = "Hello " ++ name +

我不明白
的工作方式:

let component = ReasonReact.reducerComponent("Greeting");

let make = (~name, _children) => {
  ...component,
  initialState: () => 0, /* here, state is an `int` */
  render: (self) => {
    let greeting =
      "Hello " ++ name ++ ". You've clicked the button " ++ string_of_int(self.state) ++ " time(s)!";
    <div>{ReasonReact.stringToElement(greeting)}</div>
  }
};
let component=ReasonReact.reducer组件(“问候”);
让make=(~name,_children)=>{
…组件,
initialState:()=>0,/*这里,state是一个'int'*/
呈现:(自我)=>{
让问候=
“您好”++name++“。您已单击按钮“++string_of_int(self.state)++“time(s)!”;
{ReasonReact.stringToElement(问候语)}
}
};
据我所知,
make
将在父组件渲染方法中每次使用
组件时被调用,因此它将被多次调用

但这也意味着组件记录将多次创建
initialState
函数,对吗

我不明白每次创建React元素时分配
initialState
一些函数有什么意义,而它只会在元素挂载时被调用,对更新没有影响

我以
initialState
为例,但对于其他生命周期回调也可以这样说

据我所知,
make
将在父组件渲染方法中每次使用
组件时被调用,因此它将被多次调用

是的,
make
会为每个渲染调用

make Inside
每次按下按钮时都会在控制台中打印–这会导致
Inside
组件的新渲染

我很想更好地理解为什么会发生这种情况,所以在这里分享它,以防其他人觉得有趣。今天的实施方式大致如下:

  • 被转换为
    ReasonReact.element(Greeting.make(~name=“John”,[| |]])
    ,原因是ppx。您可以找到实现
  • 在该语句中,
    Greeting.make
    是您正在引用的
    make
    函数,与每个组件必须定义的函数相同
  • ReasonReact.element
    是魔法发生的地方。此函数将按以下方式调用
    createElement
createElement(
component.reactClassInternal,
~props={“key”:key,“ref”:ref,“reasonProps”:element},
[||]
)
  • 作为prop
    reasonProps
    传递的
    元素实际上是由
    make
    返回的完整组件“模板”(请参见分配)
  • component.reactClassInternal
    指向一个React组件,为了简单起见,我将调用该组件。这个
    WiringComponent
    本质上是声明所有React生命周期方法,并通过将实际行为委托给使用
    make
    声明的“模板”中的函数来实现它们。这些函数是从传递到此
    WiringComponent
    reasonProps
    属性中选取的。您可以看到该组件的实现
因此,即使像您提到的那样,每次渲染都会调用一次
make
,但实际上渲染的内容类似于
。然后,当调用
WiringComponent.getInitialState
时(通常每个组件实例只调用一次)

但这也意味着组件记录将多次创建
initialState
函数,对吗


代码似乎就是这么做的。解决这个问题对我来说并不是一件小事。考虑到标签参数被用于对组件道具建模,在不放弃类型安全性的情况下,无法记忆
make
,因为此函数可能有许多“风格”(每个组件一个)。

如果初始状态不依赖于初始道具,可以将其取出:
let initialState=()=>0;让make=(~name,_children)=>{…component,initialState,render:…}当然我能做到,但当它依赖于初始道具时,我仍然看不到每次重新创建该函数的价值:)不是真的寻找性能解决方法,而是更多地了解这背后的设计决策啊,对不起。因此,由于在每次渲染时都会调用
make
initialState
需要惰性地进行评估(您在Scala中将其建模为名称调用)。这是因为它应该只在第一次
make
调用时进行评估,而不是之后。他们只是选择使用一个函数。也可以建模为OCaml
lazy
value(),但在编译的输出中,这或多或少是相同的。所以基本上你说initialState函数在那里,但实际上只有在调用它时才会被创建?因此,可能会创建多个延迟变量,但一个单独的变量将导致函数创建?正确,我看不到在当前的设计中解决这个问题的方法…感谢您的解释。不知道你所说的“味道”是什么意思。我想了解的是这个make函数背后的设计决策。难道我们不能在另一个地方声明像
initialState
这样的函数,以便每个组件实例只创建一次吗?同样,不是参与者,所以对此持保留态度(我也想知道ReasonReact的创建者会说些什么)。我所说的“口味”是指每个组件都有不同的道具类型。如果我们将其与将道具作为标记参数实现的决策结合起来,那么就很难(不可能?)有一个保存所有这些信息的“ReactComponent”记录。
呈现
函数的类型是什么样的?不幸的是,我可能还不知道足够的Ocaml来理解您的意思:)将尝试看看是否有人可以帮助我理解Discord@SebastienLorber您可以在其他地方定义函数