לא הבנתי למה בשיטה של 16 יש איזשהו גמישות שלא יכולנו לעשות ב-15 … למה ב- 15 לא יכולתי להעביר את זה הלאה לפקדים משורשרים , או כל היתרונות שהצגת בסרטון - מה ההבדל אם זה רשום אצלי במחלקה או שזה רשום כחלק מאובייקט refs שהוא גם שמור אצלי במחלקה ?
ynonp
11 באוקטובר, 2018, 6:56am
#3
הדיון המלא שהוביל לשינוי כאן:
opened 12:40AM - 08 Apr 14 UTC
closed 02:19AM - 23 Jan 15 UTC
The ref API is broken is several aspects.
- You have to refer to this.refs['myna… me'] as strings to be Closure Compiler Advanced Mode compatible.
- It doesn't allow the notion of multiple owners of a single instance.
- Magical dynamic strings potentially break optimizations in VMs.
- It needs to be always consistent, because it's synchronously resolved. This means that asynchronous batching of rendering introduces potential bugs.
- We currently have a hook to get sibling refs so that you can have one component refer to it's sibling as a context reference. This only works one level. This breaks the ability to wrap one of those in an encapsulation.
- It can't be statically typed. You have to cast it at any use in languages like TypeScript.
- There's no way to attach the ref to the correct "owner" in a callback invoked by a child. `<Child renderer={index => <div ref="test">{index}</div>} />` -- this ref will be attached where the callback is issued, not in the current owner.
I think that the solution must ultimately be some kind of first class ref that can be passed around. These refs can be chained to create multi-owner refs very efficiently. By creating this object for the ref, we can also get rid of keeping track of owners on descriptors. Saving perf for the common idiomatic case of not using refs.
A secondary goal, which may or may not be as important is the idea of making the resolution of refs asynchronous so that you can respond after a batched flush/reconciliation.
The concept of a first class ref is basically a reference to an object that doesn't exist yet. Luckily there's a first class notion of this in the language already... It's called a Promise.
You create a new Ref instance which is just Promise object that will eventually resolve to the actual instance.
``` javascript
class Foo {
myDivRef = React.createRef();
handleTick() {
this.myDivRef.then(myDivNode => {
this.setState({ width: myDivNode.offsetWidth });
});
}
render() {
return (
<C tick={this.handleTick}>
<div ref={this.myDivRef} />
<CustomComponent context={this.myDivRef} />
</C>
);
}
}
```
Since this builds on top of Promises we would be able to get async/await language features that allow us to do something like this:
``` javascript
async handleTick() {
this.setState({ width: (await this.myDivRef).offsetWidth });
}
```
This solves all those use cases AFAIK. The asynchronous API is a little difficult to deal with. But it makes it less weird than the alternative when batching is involved.
An unsolved problem is that refs can update to point to a different instance. In that case the Promise would need to be re-resolved. This is why Promises are not good enough and we ultimately need something like an Observable that can handle multiple values. We can't wait for that spec though. Maybe we just allow our promises to be reset and if you call then(...) again, you get a new value?