[react] [react-dom] Add support for rendering an array of elements#19363
[react] [react-dom] Add support for rendering an array of elements#19363johnnyreilly merged 7 commits intoDefinitelyTyped:masterfrom
Conversation
|
types/react-dom/index.d.ts to authors (@pspeter3 @vsiao @MartynasZilinskas AssureSign (account can't be detected) Microsoft (account can't be detected)). Could you review this PR? Checklist
types/react/index.d.ts to authors (@pspeter3 @vsiao @johnnyreilly @bbenezech @pzavolinsky @digiguru @ericanderson @morcerf @tkrotoff @DovydasNavickas @onigoetz @richseviora AssureSign (account can't be detected) Microsoft (account can't be detected)). Could you review this PR? Checklist
|
|
Uhmm, I guess something is clearly wrong. Checking it out. |
|
@cynecx Please fix the failures indicated in the Travis CI log. |
|
It seems that this patch doesn't affect any of the occurring errors as I can reproduce them even without this patch. Would be great if someone could review this. Thank You. |
vsiao
left a comment
There was a problem hiding this comment.
I think the react-dom changes are incorrect. Core react changes seem fine, but perhaps missing changes to SFCs?
| element: SFCElement<P>, | ||
|
|
||
| export function render( | ||
| element: Array<DOMElement<any, any>>, |
There was a problem hiding this comment.
can you link to any documentation of this API? I didn't know that it was possible to pass an array into ReactDOM.render.
There was a problem hiding this comment.
It's not yet documented but with React Fiber (v16) you can pass an array of elements to the render function.
See this test case: https://codesandbox.io/s/y310mjkp5v
The test case is using a beta release of react/react-dom (16.0.0-beta.5).
There was a problem hiding this comment.
Just as a code reference:
The parameter newChild is basically the element passed to the render function. This line in createChild checks whether the element parameter, which has been passed down to this function, is an array. If so, it deals with it respectively, in createFiberFromFragment, which indicates that React-Fiber (v16) supports passing an array of elements to the render function (react-dom).
There was a problem hiding this comment.
Thanks. Can you add type parameters for props, as in the other overloads?
There was a problem hiding this comment.
Excuse me, but how would that work? Since we don't have something like "variadic parameter types" in typescript. Am I missing something?
There was a problem hiding this comment.
It could be Array<DOMElement<DOMAttributes<any>, any>>> for the lack of better specificity, to mirror the generic overload above that has DOMAttributes<T> as the props.
There was a problem hiding this comment.
I agree. I've commited the change you suggested. Thanks.
|
Rebased the feature branch. |
| element: Array<CElement<any, Component<any, ComponentState>>>, | ||
| container: Element | null, | ||
| callback?: () => void | ||
| ): Component<any, ComponentState>; |
There was a problem hiding this comment.
should this be an array return value?
There was a problem hiding this comment.
I don't think so. It seems that React-Fiber does not return the whole array which is somewhat strange. According to my tests, it only returns the first element of the array.
There was a problem hiding this comment.
Using render's return value is itself deprecated (it's planned to become fully async in the future). Function refs should be used instead.
I'd be in favor of declaring this as void even though it's de facto wrong.
There was a problem hiding this comment.
I would leave this as it is for now. When it's finally changed we can reflect the changes afterwards. It may be deprecated but some users might still use this in their code. I guess it's better this way.
There was a problem hiding this comment.
At least adding a comment with a deprecated tag should be enough in my opinion.
There was a problem hiding this comment.
Where would you like to add them? Marking the whole render function as deprecated doesn't feel right (Using jsdoc's @deprecated). Or do you think a simple comment would be sufficient?
There was a problem hiding this comment.
I thought something with function overload. But other than that, simple comment should be enough.
There was a problem hiding this comment.
I've pushed a new commit which adds a deprecated comment.
|
It seems that there is an issue in I am not sure how to fix this issue. We can either assume that the render function in the class Route from react-router always returns a JSX.Element or we can modify the test. We could modify the Route class like the following: Should this go in a new PR? |
|
@cynecx I'm thinking it's probably best to update the broken tests ( |
|
Rebased on master. I am working on fixing the tests now. |
|
Seems good now. There is just one error which I am certain that this PR didn't affect: |
|
Flagging some users for approval: @prakarshpandey, @Andy-MS, @mtpc, @tkrotoff, @MartynasZilinskas |
|
Any update on this? |
|
@circlingthesun Well, I am still currently waiting for approval :) |
|
Hi @cynecx, tests should be fixed if you merge in the latest master. |
|
@Andy-MS Okay. I am not sure how this PR caused that last one but I'll fix it :) |
|
Thanks all! |
|
It seems it breaks a simple case: import * as React from "react";
import * as ReactDOM from "react-dom";
class Main extends React.Component<{}, {}> {}
ReactDOM.render(<Main />, document.getElementById("container")); // <- error hereerror TS2345: Argument of type 'Element' is not assignable to parameter of type 'ReactElement<any>[]'.
Property 'length' is missing in type 'Element'. |
|
@plantain-00 I am not able to reproduce this. Your simple case compiles just fine here. What version of typescript are you currently using? |
|
|
@plantain-00 could you put together a minimal repro repo to share please? That will help things move quicker |
|
Based on @plantain-00's observation, I managed to work around this by adding the following to my package.json (I'm using yarn). |
|
it's OK now, there is a |
|
This does not work: render() {
return this.props.children;
}Question: why do we have |
|
@tkrotoff Since when we can return |
|
@MartynasZilinskas You're right, see https://codepen.io/tkrotoff/pen/yzKKdB Still there is a problem: render() {
const { children } = this.props;
return children !== undefined ? children : null;
} |
|
Has the above fix been added for stateless components? I'm getting an error when attempting to implement one that returns an array of elements |
|
why was the generic version of export function findDOMNode<E extends Element>(instance: ReactInstance): E;(tagging @cynecx) |
|
@patsissons it was removed because of a lint failure. Does it suffice to convert usages like so? before: ReactDOM.findDOMNode<HTMLInputElement>(inst)after: <HTMLInputElement>ReactDOM.findDOMNode(inst) |
|
yea i am doing (basically) this as a temporary patch. what is the type safe way of finding a dom node of a specific type (i.e., my use case is that i am finding a dom node that will then be focused, so i need the type to be derived from I guess the argument is that the previous typing was no more type safe than a direct cast, in which case I understand why the change was made. |
|
@patsissons, you will NOT get a type-safe result from a function What you CAN do is have a type-gate for checking if an |
|
@patsissons I think the typecast is equivalent to what you were doing before. As @DovydasNavickas mentioned there's no guarantee that |
|
I have to imagine that the equivalence of |
|
@cynecx I think you forgot about functional components. The following code doesn't work and the error
|
|
@niba Seems so. Looks like a trivial change to me. I can open a PR later. |
|
@cynecx I have been trying to add this on my own but it doesn't look like a trivial change. Simple changing the return type of StatalessComponent function breaks JSX with this change, the below definition of functional component started working but now it's impossible to call it from JSX.
I don't see any constructor function in ReactElement and I don't know how JSX is processed by typescript. Do you have any idea what is wrong? |
|
@niba You are right, this doesn't look trivial. I am also not sure what's wrong here (I am not too familiar with this code) but I will try investigating this. |
|
I don't have much time to look into this, but there's some useful background in microsoft/TypeScript#5478 about how SFC+TSX works. cc @RyanCavanaugh |
|
I get an error when I try to return an array that contains a null element from Maybe this isn't an idiomatic way of conditionally rendering an element inside of an array (still becoming acquainted with Fiber), but React deals with this how I would expect. TypeScript throws the following error: |
|
@notitatall the return type of |
npm run lint package-name(ortscif notslint.jsonis present).tslint.jsoncontaining{ "extends": "dtslint/dt.json" }.Changes:
ReactDOM::renderto support rendering an array of elementsanyinstead of a deduced typeI am not quite sure if these changes are correct, so please be gentle on reviewing these changes ;)