-
Notifications
You must be signed in to change notification settings - Fork 5
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
Rules for property accesses #4
Comments
Idea: When accessing Triggers warning: function App({ myRef /* is ref: unknown */ }) {
useAutoEffect(() => {
myRef.current
})
return null
} Does not trigger warning: function App({ myRef }) {
markRef(myRef) // is ref: true
useAutoEffect(() => {
myRef.current
})
return null
} function App({ myRef }) {
markNonRef(myRef) // is ref: false
useAutoEffect(() => {
myRef.current
})
return null
} function App() {
const myRef = useRef() // is ref: true
useAutoEffect(() => {
myRef.current
})
return null
} function App({ myRef /* is ref: unknown */ }) {
const { current } = myRef
useAutoEffect(() => {
current
})
return null
} |
If the default behavior is to add the object to dependencies and show a warning, it would probably not break a lot of code. |
The algorithm
Determine status
Error message
markRef/markNonRef
|
Is it possible to have e.g. function MyComponent({ config }) {
const __asdfanasdfjl__ = config.value;
return useMemo(() => __asdfanasdfjl__ * 2, [__asdfanasdfjl__]);
} |
@neoncube2 yeah that is the plan, the problem is that accessing a property is not pure/idempotent (think property getters) and some ordering may need to be respected. @adrianhelvik your approach is actually very clean! I’ll look into it! (Sorry for the huge delay!) |
No worries. That's great news! 🙂 |
Thanks, @yuchi. I wonder if the ordering really needs to be respected, though? My understanding is that |
@neoncube2 Yes, render functions are pure, but callbacks and effect callbacks can (and usually indeed are) impure. |
Some important things to consider is conditionals, const [config, configure] = useState()
const ref = useAutoCallback(element => {
configure({
actions: {
click() { element.click() }
}
})
})
useAutoEffect(() => {
if (!element) return
config.actions.click()
})
return <button ref={ref}>Click me!</button> (Train of thought)Would break if transpiled into: var _click = config.actions.click
useEffect(() => {
if (!element) return
_click()
}, [_click]) An alternative would be to transpile into: var _click = config?.actions?.click
useEffect(() => {
if (!element) return
_click()
}, [_click]) But that would change the const ref = useAutoCallback(element => {
configure({
element,
click() { this.element.click() }
})
}) So the original input... Should leave us with something like: // ...
var _click = config?.actions?.click
useEffect(() => {
if (!element) return
_click.call(config.actions)
}, [element, _click])
// ... Edit: Then again, I don't think supporting impure getters should be the highest priority as it complicates the implementation for minimal gain. Without support for impure getters, there will be no need to handle // ...
useEffect(() => {
if (!element) return
config.actions.click()
}, [element, config?.actions?.click])
// ... |
Because accessing a property in a callback could reference different values that the ones are available at function definition, we currently do not add property accesses to the inputs array. For example:
Gives this output:
This is a big issue when dealing with refs, which are a
{ current }
object. Since they are mutable, this makes the problem non-trivial.The text was updated successfully, but these errors were encountered: