0

After calling

<MyComponent x="aaa" y="bbb" key="0" ref={someRef}/>

the props object is

{ x: 'aaa', y: 'bbb' }

in React and Inferno, but it is

{ x: 'aaa', y: 'bbb', key: '0', ref: someRef }

in Preact.

Does anybody know the reasons for those different design decisions and maybe some advantages and disadvantages of each solution?

Chris
  • 57,622
  • 19
  • 111
  • 137
Natasha
  • 516
  • 7
  • 24

2 Answers2

1

This answer is taken from React GitHub Issues

The reason is that the concept of a key is something that is controlled by React internals before your component gets created. The same thing for refs. You can think about an array of ReactElements as a Map.

A Map is a series of key and value tuples. A React fragment is a series of key and props tuples (and also type and ref). The key is designed to decide what the value is in each slot, but not the actual value itself.

If you're reading a prop named key you might be overloading the meaning of key or accidentally using it for something unrelated.

This change makes the concept a bit more strict. This helps avoids bugs with transferring props to another component which shouldn't bring the key and ref along with it. It also helps performance by ensure that types in React internals are consistent and stable.

I would suggest renaming or duplicating the prop name as a possible fix if you really need to access it.

Community
  • 1
  • 1
Amir-Mousavi
  • 4,273
  • 12
  • 70
  • 123
1

Disclaimer: I work on preact.

Passing both the key and ref prop into a component was a bug that we fixed for our upcoming major release. An alpha is scheduled to land on March 4th 2019.

There is even an open RFC to pass ref via props again. We're very supportive of that change, because that would make forwardRef redundant.

marvinhagemeister
  • 2,801
  • 1
  • 22
  • 27
  • May I ask an additional question: After the first alpha of "Preact 10" is out now, I've seen that - as you have written above - it does not have a `forwardRef` function and property `key` is no longer part of props. But also property `ref` is no longer part of props, which I think is a bit confusing - how do implement something like `useImperativeHandle` then? – Natasha Mar 05 '19 at 09:47
  • 1
    `forwardRef` is available in `preact/compat` that ships in the same npm package. Not passing `key` into `props` is the correct behaviour. It's the same way with react. See: https://codesandbox.io/s/1q0krzl6v7 – marvinhagemeister Mar 05 '19 at 10:10
  • Sorry for being unclear, I meant (forget about "compat" for a moment, I'm just interested in the "normal" Preact module here): Why is in Preact 10 `ref` NOT part of `props`? How is it possible to implement something like `useImperativeHandle` if you do not have access to `ref` from inside a function component? – Natasha Mar 05 '19 at 10:30
  • 1
    That's currently only possible with `forwardRef` from `compat`. You could workaround it bypassing the ref via a different prop to your component. Something like `` . `ref` is not part of `props` because that's the way it's done in `react` and we received bugs that we were deviating from them. – marvinhagemeister Mar 05 '19 at 11:50