Skip to content

Instantly share code, notes, and snippets.

@gaearon
Last active January 11, 2024 16:56
Show Gist options
  • Save gaearon/8fa9fdd2c4197ee0b52894877bf587a4 to your computer and use it in GitHub Desktop.
Save gaearon/8fa9fdd2c4197ee0b52894877bf587a4 to your computer and use it in GitHub Desktop.

A top-level App component returns <Button /> from its render() method.

  1. What is the relationship between <Button /> and this in that Button’s render()?

  2. Does rendering <Button><Icon /></Button> guarantee that an Icon mounts?

  3. Can the App change anything in the Button output? What and how?


Update: answers are here!

@djsmith42
Copy link

  1. <Button /> is a virtual DOM element (represented in JSX here), but this in Button's render() method refers to the instance of the Button component, which is different. Components have a render() method which returns elements.
  2. No. The Button component could chose not to render its children.
  3. I don't quite understand this question, but here's one idea. The App could write to some really gross global variables that the Button uses to decide what to render. Also, the App could pass props to the Button, which could influence the Buttons output, if Button is written that way.

@vutran
Copy link

vutran commented Sep 28, 2016

Components have a render() method which returns elements.

@djsmith42 I may be wrong but to be clear, I think it should return an array of instances of components which should be virtual DOM elements, not DOM elements. If that's incorrect, can you please clarify?

@jvaill
Copy link

jvaill commented Sep 28, 2016

  1. <Button /> is a virtual DOM representation of said component. this in that Button's render() is an instance of the Button component. There is only one active instance for one <Button />, but React reserves the right to unmount, mount, and recreate that instance under different circumstances.
  2. No, the Button component might not render its children.
  3. There are three ways for App to change the Button's output, a) by passing props, b) by setting state using refs, c) by setting context. All three assume that Button changes its output based on those mechanisms.

Edit: 3. -> The other way is indirectly via architectures such as flux and redux. ;)

@harmony7
Copy link

harmony7 commented Sep 28, 2016

Components have a render() method which returns elements.
@djsmith42 I may be wrong but to be clear, I think it should return an array of instances of components which should be virtual DOM elements, not DOM elements. If that's incorrect, can you please clarify?

@djsmith42 @vutran A single render() method can return only a single React element (or null). However, this single React element may have an array of React elements as its children, which in turn may each have their own children which are also React elements, and so on.

EDIT: clarified that "element" means "React element"

@frankpinto
Copy link

frankpinto commented Sep 29, 2016

  1. translates into React.createElement(Button) so it should return an instance of the React Component. this inside the Button's render method should also point to the instance rendered by React so I'm going to say both and this point to the same object.
  2. rendering them does, yes. As in, returning them from the render method. Typing them out and assigning it to a variable doesn't, unless you then return that variable.
  3. can pass props to when it renders.

@vutran
Copy link

vutran commented Sep 29, 2016

@djsmith42 @vutran A single render() method can return only a single React element (or null). However, this single React element may have an array of React elements as its children, which in turn may each have their own children which are also React elements, and so on.
EDIT: clarified that "element" means "React element"

@harmony7 Yes, sorry to clarify my previous, I was referring to render() returning a single vDOM element that could contain children vDOM elements. These vDOM elements, when mounted to the DOM, becomes DOM elements.

So for example:

const App = () => ( // pure component... basically render()
  <Button>
    <Icon />
    <img src="foo.png" />
  </Button>
);

In the example above, Button have 2 child: Icon and img which are both vDOM elements. Note that <img /> is a valid DOM element but at this stage, it is still a vDOM element.

@LubergAlexander
Copy link

LubergAlexander commented Sep 29, 2016

  • What is the relationship between and this in that Button’s render()?
    this will be the button's instance -> this.setState will set state of the button
  • Does rendering <Button><Icon /></Button> guarantee that an Icon mounts?
    No. it can skip rendering children
  • Can the App change anything in the Button output? What and how?
    yes, you can clone children elements in the App and change their props, for example, but I don't really understand the question.

@chitchu
Copy link

chitchu commented Sep 29, 2016

What is the relationship between <Button /> and this in that Button’s render()?

this in <Button/>'s render() is a Button React Component object.

Does rendering <Button><Icon /></Button> guarantee that an Icon mounts?

No. Only if the <Button/> component returns props.children in it's render method.

Can the App change anything in the Button output? What and how?

Passing down props or child components to the <Button/>.

@SukantGujar
Copy link

SukantGujar commented Sep 29, 2016

  1. The App component's render method returns a Button Element, which is not the same as Button Component class. This Button element instance has this structure -

    {
        type: Button, // points to the Button Component class since it's a custom Component, not a primitive.
        props:{...}
    }
    

    When the element is actually mounted, React will use this information to create a Button Component class instance, which will be the value of this inside the Button Component's render.

  2. The will be mounted if App has mounted Button and the render of Button returns {this.props.children}.

  3. Yes, App can change what Button renders through props, or using a HOC on it.

@hon2a
Copy link

hon2a commented Sep 29, 2016

  1. <Button /> is a React.Element - a description of what is to be rendered. Most importantly it says that a Button instance is needed for the render and which props should be passed to it. this refers to that Button instance.
  2. No, it only passes <Icon /> to the Button as props.children. What mounts inside the Button depends solely on the Button (namely its render and shouldComponentUpdate).
  3. If by "Button output" you mean the React.Element description returned by its render(), then no. It controls what's passed to Button in props and it can later act on the Button instance, but it has no way to access the React.Element returned from Button's render().

@reel
Copy link

reel commented Sep 29, 2016

  1. this belongs to Button
  2. Button has to explicitly output children
  3. With props

@Rom325
Copy link

Rom325 commented Sep 29, 2016

Regarding the third question, how about an ugly way?

class App extends React.Component{
    render(){
        const button = React.Children.only(this.props.children)
        if (typeof button.type.prototype.render === "function"){
            button.type.prototype.render = () => <span>"Changed completely"</span>;
        }

        return (<div>{ this.props.children } </div>);
    }
}

Btw it won't work for stateless functional components

@danielpetrov
Copy link

1.Q- What is the relationship between and this in that Button’s render()?
1.A- '< Button />' == React.createElement('Button'). Button is created with React.createClass which expects object specification. In those object specification there is render method and this points to that object instance. React.createElement('Button') or '< Button />' creates new instance of that type. So the this in Button's render method is almost the '< Button />' but not exactly. The '< Button />' instance is created via React and not native Object.create().

2.Q- Does rendering

guarantee that an Icon mounts?
2.A- Never. Button may choose to not render it's children.

3.Q- Can the App change anything in the Button output? What and how?
3.A- One way is directly via props. Button also may be connected to some store on which App is connected. Also it can change it directly through passing different children to Button.

@wmira
Copy link

wmira commented Sep 30, 2016

  1. defines the tree..with type as Button. this in Button is the actual instance created based on tree.
  2. No. the in the is just a description of the tree of elements. It is still possible for the Button instance to ignore it.
  3. via props if permitted by Button

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment