Container Component Pattern in React
- Richa Pujara
Intern at Back2.Dev
{Richa Pujara is fully pure}

{ Why? }

& Container Component Pattern
- What are these?
- How to use them?
- Applicability IRL
- Storybook - Testing Buddy
- My thoughts
{ Overview }
{ What is it? }
Pure component (props)
* Display
* User interaction
Container
* Fetches data
* Saves data
Storybook
* Provides different data sets
* Logs actions (eg save)
Pure component (props)
* Display
* User interaction

{ A way of writing code.. }
import React from 'react';
export default function DogImages() {
const [dogs, setDogs] = React.useState([])
React.useEffect(() => {
fetch("https://dog.ceo/api/breed/labrador/images/random/6")
.then(res => res.json())
.then(jsonRes => setDogs(jsonRes.message));
}, [])
const myStyle = {
border: '1px solid black',
width: "80vw",
height: "80vh",
backgroundColor: "grey",
overflow: "scroll",
textAlign: "center",
}
return (
<>
<div>
<h2 className="heading">Dogs Images</h2>
</div>
<div style={myStyle}>
{dogs.map((dog, i) => <img src={dog} key={i} alt="Dog" width={'100%'} height={'100%'} />)}
</div>
</>
)
}
# PRESENTING CODE
// DogsUI.js -- Presentational Component
import React from "react";
import PropTypes from 'prop-types'
function DogImages({ dogs, ...props }) {
const myStyle = {
border: props.border || '1px solid black',
width: props.width || "80vw",
height: props.height || "80vh",
backgroundColor: props.backgroundColor || "grey",
overflow: "scroll",
textAlign: props.alignment || "center",
}
return (
<div style={myStyle}>
{dogs.map((dog, i) => {
<img src={dog} key={i} alt="Dog" width={props.imgwidth || '100%'} height={props.imgheight || '100%'} />
})}
</div >
)
}
export default DogImages
# PRESENTATIONAL COMPONENT
{A Better way of doing it}
// dogsContainer.js -- Container Component
import React from 'react';
import DogImages from './DogsUI'
export default function DogImagesContainer() {
const [dogs, setDogs] = React.useState([])
React.useEffect(() => {
fetch("https://dog.ceo/api/breed/labrador/images/random/6")
.then(res => res.json())
.then(jsonRes => setDogs(jsonRes.message))
}, [])
return <DogImages dogs={dogs} />;
# CONTAINER COMPONENT
Container
* Fetches data
* Saves data
Pure component (props)
* Display
* User interaction
Context (shared state)
Container
* Fetches data
* Saves data
List
Context / shared state (also pure)
Add
Edit
View

{ Applicability IRL }
Storybook
import React from 'react';
import Dogs from './DogsUI';
export default {
title: 'Dogs',
component: Dogs,
argTypes: {
backgroundColor: { control: 'color' },
height: { control: 'select', options: ['50vh', '60vh', '70vh', '80vh', '90vh', '100vh'] },
imgheight: { control: 'select', options: ['50px', '100px', '150px', '200px', '250px', '300px'] },
width: { control: 'select', options: ['50%', '60%', '70%', '80%', '90%', '100%'] },
imgwidth: { control: 'select', options: ['50%', '60%', '70%', '80%', '90%', '100%'] },
alignment: { control: 'select', options: ['center', 'left', 'right'] }
}
};
const Template = (args) => <Dogs {...args} />;
// Test Stories with different scenarios:
export const DogsImages1 = Template.bind({});
DogsImages1.args = {
dogs: ["https:\/\/images.dog.ceo\/breeds\/labrador\/n02099712_2174.jpg", "https:\/\/images.dog.ceo\/breeds\/labrador\/n02099712_389.jpg", "https:\/\/images.dog.ceo\/breeds\/labrador\/n02099712_5017.jpg", "https:\/\/images.dog.ceo\/breeds\/labrador\/n02099712_7133.jpg", "https:\/\/images.dog.ceo\/breeds\/labrador\/n02099712_7179.jpg", "https:\/\/images.dog.ceo\/breeds\/labrador\/n02099712_7749.jpg"],
};
export const DogsImages2 = Template.bind({});
DogsImages2.args = {
dogs:["https:\/\/images.dog.ceo\/breeds\/labrador\/n02099712_3273.jpg", "https:\/\/images.dog.ceo\/breeds\/labrador\/n02099712_5000.jpg", "https:\/\/images.dog.ceo\/breeds\/labrador\/n02099712_5471.jpg", "https:\/\/images.dog.ceo\/breeds\/labrador\/n02099712_6684.jpg", "https:\/\/images.dog.ceo\/breeds\/labrador\/n02099712_7963.jpg", "https:\/\/images.dog.ceo\/breeds\/labrador\/n02099712_8051.jpg"]
};
export const CatsImages3 = Template.bind({});
CatsImages3.args = {
dogs:["https://cdn2.thecatapi.com/images/3gv.jpg", "https://cdn2.thecatapi.com/images/4cl.gif", "https://cdn2.thecatapi.com/images/b8p.jpg", "https://cdn2.thecatapi.com/images/bvu.jpg", "https://cdn2.thecatapi.com/images/MTczNTkwNA.jpg"],
border: "1px solid red"
};
# PRESENTING CODE
{ And I think... }
{ Why containers? }
-
Separation of APIs/ App logic from Presentational part
-
Reusability of components
-
Sharing states
-
Makes App structure easier to understand
Answer to a big question..

Thank You...
Container Pattern in React
By richap
Container Pattern in React
- 34