-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(view): fix the forwardRef functionality for view #5
base: master
Are you sure you want to change the base?
Conversation
The code looks great to me, but for some reason it's not rerendering when the store changes. I have no idea why 😅 |
I've recorded this reply https://www.loom.com/share/b98cdb54e51d45c6b024a0f1465e68f8 TL;DR; at the end of the day, forwardRef wraps the memoed render function but it should be the other way around. Still investigating it. |
How bad is to do |
That doesn't work either. I mean that's what we do right now. Yesterday though, I went on anther direction with it, and I think it's all related to how |
I'm not sure what you mean by that. The way it works is by wrapping the component in an The The computation tracks all the reads done during the computation execution. This should work just fine: observe(
(() => {
(() => {
state.some.prop;
})();
})()
); The rerender is triggered by the |
Now that we use a reference ( EDIT: This is what I was trying. ReactiveComp = (props, ref) => {
// use a dummy setState to update the component
const [, setState] = useState();
// use a ref to store the reaction
const reaction = useRef(null);
// create a reactive wrapper of the original component (render)
// at the very first run of the component function
if (!reaction.current) {
reaction.current = observe(Comp, {
scheduler: () => {
// trigger a new rerender if the component has been mounted
if (reaction.current.mounted) setState({});
// mark it as changed if the component has not been mounted yet
else reaction.current.changedBeforeMounted = true;
},
lazy: true,
});
// initilalize a flag to know if the component was finally mounted
reaction.current.mounted = false;
// initilalize a flag to know if the was reaction was invalidated
// before the component was mounted
reaction.current.changedBeforeMounted = false;
}
useEffect(() => {
// mark the component as mounted.
reaction.current.mounted = true;
// if there was a change before the component was mounted, trigger a
// new rerender
if (reaction.current.changedBeforeMounted) setState({});
// cleanup the reactive connections after the very last render of the
return () => unobserve(reaction.current);
}, []);
// run the reactive render instead of the original one
return isForwardRef
? forwardRef(reaction.current(props, ref))
: reaction.current(props);
}; |
Additional thing to consider is that a forwardRef component is an object with a import { Component, forwardRef } from "react";
class ClassComp extends Component {
render() {
return <div>I am the Foo</div>;
}
}
const FuncComp = () => <div> hello </div>;
const Fwd = forwardRef((props, ref) => <div ref={ref} {...props} />);
console.log(typeof ClassComp); // 'function'
console.log(typeof FuncComp); // 'function'
console.log(typeof Fwd); // 'object' There is known bug which is that I was able to get around it by changing this line to: // check if the fn is actually a forward_ref object and in that case call its `render` method
if (typeof fn === 'object' &&
fn !== null &&
fn.$$typeof === Symbol.for('react.forward_ref')
) {
return Reflect.apply(fn.render, context, args);
}
return Reflect.apply(fn, context, args); However, I did not dig deep enough to be 100% certain that it's the complete solution. PS. This should be fixed in https://github.com/frontity/observer-util, but I'm documenting this here for completeness. |
For context, Cris is trying to fix this in: frontity/observer-util#2 I asked him if we could do this in |
Hey guys, what is the status of this? Any progress? 🙂 |
Resolves frontity/frontity#773
Proposed changes:
This one fixes the
forwardRef
usage together with theview
components.This was part of our pair programming session @luisherranz. Let me know if I borked something up 😄