score:0

along with newtop you can return a function that triggers recalculation of the newtop. similar to how usestate does. and invoke it onafteropen.

score:2

indeed, the rules of hooks says:

https://reactjs.org/docs/hooks-rules.html

only call hooks at the top level

don’t call hooks inside loops, conditions, or nested functions. instead, always use hooks at the top level of your react function. by following this rule, you ensure that hooks are called in the same order each time a component renders. that’s what allows react to correctly preserve the state of hooks between multiple usestate and useeffect calls. (if you’re curious, we’ll explain this in depth below.)

this is necessary for react to be sure that hooks will be called on exact the same order in every render cycle.

it seems that modal would call usetop only after mounted (opened), i.e. it will probably have skipped the first render, violating the rule of hooks and messing with the order.

one thing you can try:

pass the ref for your usetop hook and handle it inside of it. if it's null, don't do anything, if it's already mounted, attach the listener and return the cleanup function.

const panel = () => {
  const newtop = usetop(contentref);
  <modal pos={newtop} onafteropen={null}><div ref={contentref}>test</div></modal>
};

Related Query

More Query from same tag