Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I add properties to a react component passed as a variable?

Tags:

reactjs

My scenario is that I'm creating a render() function in a controller (not React related) to render views with the option of specifying a layout. That way I can have multiple different layout components, all accepting a content property, that can be rendered in a simple way. Here's what I'm trying to do in a nutshell:

render: function(content, layout) {
    layout = layout || <Layout />;
    layout.setProps({ content: content });
    React.render(layout, document.body);
}

Can it be done? Or if you think it can be done but it's a bad idea, please let me know why.

like image 545
Rocket04 Avatar asked Mar 07 '15 15:03

Rocket04


People also ask

How do you pass props to ReactJs component that wrapped in variable?

cloneElement() method used here. This method is used to create the clone of the element that will be given as an argument, also here we can pass props and children as arguments. Here variable “c” is passed as an element in React. cloneElement() method for cloning, also passed props {name1: “C++”, name2: “JAVA”}.

Can you conditionally add attributes to components in React?

You can use any logic and conditionals in order to build the object. You will most commonly use the ternary operator to add conditional attributes to an element in React.

How do you add a prop to an existing component React?

One of the ways we can add new props to the children is by using React. cloneElement() like so: const newProps = { className: 'hidden', onClick: () => alert('test') }; const MyComponent = ({ children }) => ( <div> {children. map(child => React.

How do you change properties in React component?

A component cannot update its own props unless they are arrays or objects (having a component update its own props even if possible is an anti-pattern), but can update its state and the props of its children.


1 Answers

There are a couple ways you could approach this.

The simplest is to pass the layout's type and properties separately:

function render(content, layoutType, layoutProperties) {
  layoutType = layoutType || Layout;
  layoutProperties = layoutProperties || {};

  var props = { content: content };
  for (var key in layoutProperties) {
    props[key] = layoutProperties[key];
  }

  var layout = React.createElement(layoutType, props);

  React.render(layout, document.body);
}

render(<div>Test 1</div>);
render(<div>Test 2</div>, CustomLayout, { title: "Test Title" });

JSFiddle example: http://jsfiddle.net/BinaryMuse/hjLufbkz/

If you want to pass a fully-realized ReactElement as the layout instead, you could use React.addons.cloneWithProps (or, in v0.13 RC2 and later, React.cloneElement):

function render(content, layout) {
  var props = { content: content };
  layout = layout || <Layout />;
  layout = React.addons.cloneWithProps(layout, props);

  React.render(layout, document.body);
}

render(<div>Test 1</div>);
render(<div>Test 2</div>, <CustomLayout title="Test Title" />);

JSFiddle example: http://jsfiddle.net/BinaryMuse/8krawhx4/


I'm a big fan of using this.props.children to nest elements; note that you can modify both the techniques above to do so:

function render(content, layoutType, layoutProperties) {
  layoutType = layoutType || Layout;
  layoutProperties = layoutProperties || {};

  var layout = React.createElement(layoutType, layoutProperties, content);

  React.render(layout, document.body);
}

JSFiddle example: http://jsfiddle.net/BinaryMuse/6g8uyfp4/

and

function render(content, layout) {
  layout = layout || <Layout>{content}</Layout>;
  layout = React.addons.cloneWithProps(layout, {children: content});

  React.render(layout, document.body);
}

JSFiddle example: http://jsfiddle.net/BinaryMuse/nadv297h/

Of course, if one of your custom layout components already utilizes this.props.children for other purposes, the original technique with cloneWithProps/cloneElement and this.props.content works just fine. (JSFiddle example: http://jsfiddle.net/BinaryMuse/b5ncfnqh/)

like image 103
Michelle Tilley Avatar answered Oct 06 '22 20:10

Michelle Tilley