98 lines
3.3 KiB
Markdown
98 lines
3.3 KiB
Markdown
---
|
||
title: React Component with Dot Notation
|
||
date: 2019-02-19 11:45:47 +07:00
|
||
modified: 2019-02-20 11:45:47 +07:00
|
||
categories: tips
|
||
tags: [react, javascript, dot-notation]
|
||
image:
|
||
---
|
||
|
||
This is my answer to someone’s question on [StackOverflow](https://stackoverflow.com/questions/49256472/react-how-to-extend-a-component-that-has-child-components-and-keep-them/49258038#answer-49258038). How can we define a React component that is accessible through the dot notation?
|
||
|
||
Take a look at the following code. We have the ```Menu``` component and its three children ```Menu.Item:```
|
||
|
||
const App = () => (
|
||
<Menu>
|
||
<Menu.Item>Home</Menu.Item>
|
||
<Menu.Item>Blog</Menu.Item>
|
||
<Menu.Item>About</Menu.Item>
|
||
</Menu>
|
||
);
|
||
|
||
How can we define a component like ```Menu```? Where it has some kind of “sub-component” that is accessible through a dot notation.
|
||
|
||
Well, it’s actually a pretty common pattern. And it’s not really a sub-component, it’s just another component being attached to another one.
|
||
|
||
Let’s use the above ```Menu```component for example. We’ll put this component to its own dedicated file: ```menu.js```. First, let’s define these two components separately on this module file:
|
||
|
||
// menu.js
|
||
import React from 'react';
|
||
|
||
export const MenuItem = ({ children }) => <li>{children}</li>;
|
||
|
||
export default const Menu = ({ children }) => <ul>{children}</ul>;
|
||
|
||
It’s just a simple functional component. The ```Menu``` is the parent with ```ul``` tag. And the ```MenuItem``` will act as its children. Now we can use these two components like so:
|
||
|
||
import React from 'react';
|
||
import { render } from 'react-dom';
|
||
import Menu, { MenuItem } from './menu';
|
||
|
||
const App = () => (
|
||
<Menu>
|
||
<MenuItem>Home</MenuItem>
|
||
<MenuItem>Blog</MenuItem>
|
||
<MenuItem>About</MenuItem>
|
||
</Menu>
|
||
);
|
||
|
||
render(<App />, document.getElementById('root'));
|
||
|
||
Where’s the dot notation? To make our MenuItem component accessible through the dot nation, we can simply attach it to the Menu component as a static property. To do so, we can no longer use the functional component for Menu and switch to the class component instead:
|
||
|
||
// menu.js
|
||
import React, { Component } from 'react';
|
||
|
||
export default const MenuItem = ({ children }) => <li>{children}</li>;
|
||
|
||
export default class Menu extends Component {
|
||
static Item = MenuItem;
|
||
|
||
render() {
|
||
return (
|
||
<ul>{this.props.children}</ul>
|
||
);
|
||
}
|
||
}
|
||
|
||
Now we can use the dot notation to declare the ```MenuItem``` component:
|
||
|
||
import React from 'react';
|
||
import { render } from 'react-dom';
|
||
import Menu from './menu';
|
||
|
||
const App = () => (
|
||
<Menu>
|
||
<Menu.Item>Home</Menu.Item>
|
||
<Menu.Item>Blog</Menu.Item>
|
||
<Menu.Item>About</Menu.Item>
|
||
</Menu>
|
||
);
|
||
|
||
render(<App />, document.getElementById('root'));
|
||
|
||
You can also put the ```MenuItem``` component definition directly within the ```Menu``` class. But this way you can no longer import ```MenuItem``` individually.
|
||
|
||
import React, { Component } from 'react';
|
||
|
||
export default class Menu extends Component {
|
||
static Item = ({ children }) => <li>{children}</li>;
|
||
|
||
render() {
|
||
return (
|
||
<ul>{this.props.children}</ul>
|
||
);
|
||
}
|
||
}
|
||
|
||
**For demo purpose**, Originally published at <https://bagja.net>. |