Senior Software Engineer @ Red Hat
Github: rohitkrai03
Twitter: rohitkrai03
Design patterns are typical solutions to common problems in software design. Each pattern is like a blueprint that you can customize to solve a particular design problem in your code.
React design patterns are used to simplify large React applications and helps your team to build separate components and share logic between them.
Design Patterns are the recipes that help us cook delicious React Apps.
A higher-order component (HOC) is a function that takes a component and returns a new component.
A Higher Order Component is just a React Component that wraps another one.
The “wraps” part of the definition is intentionally vague because it can mean one of two things:
const withUpperCaseUsername = (WrappedComponent) => (props) => {
return (
<div>
<WrappedComponent {...props}>
{props.children.toUpperCase()}
</WrappedComponent>
</div>
)
}
const Username = (props) => (
<div>{props.children}</div>
)
const UpperCaseUsername = withUpperCaseUsername(Username);
const App = () => (
<div>
<UpperCaseUsername>Rohit Rai</UpperCaseUsername> //ROHIT RAI
</div>
);
// This might come from a config file for example
const featureToggles = {
helloWorld: true
};
const withFeatureToggle = (feature, WrappedComponent) => {
return class extends React.Component {
render() {
if (!featureToggles[feature]) {
return null;
} else {
return <WrappedComponent {...this.props} />;
}
}
};
}
const HelloWorld = () => <h1>Hello world</h1>;
const HelloWorldWithToggle = withFeatureToggle("helloWorld", HelloWorld);
render(<HelloWorldWithToggle />, document.getElementById("root"));
The term “render prop” refers to a technique for sharing code between React components using a prop whose value is a function.
A component with a render prop takes a function that returns a React element and calls it instead of implementing its own render logic.
A render prop is a function prop that a component uses to know what to render.
const sum = (a, b) => {
const result = a + b;
console.log(result);
}
const sum = (a, b, fn) => {
const result = a + b;
fn(result);
}
// Usage
sum(1, 2, (result) => {
console.log(result);
});
sum(3, 5, (result) => {
alert(result);
});
const HelloWorld = (props) => props.render('Rohit Rai');
<HelloWorld render={(data) => <h1>My Name is {data}</h1>} />
class ResourceList extends React.Component {
state = { list: [] };
fetchData() {
axios.get(this.props.link)
.then((response) => {
this.setState({
list: response.data,
});
})
}
componentDidMount() {
this.fetchData();
}
render() {
return this.props.render(this.state);
}
}
class RandomResources extends React.Component {
render() {
return (
<ResourceList
link="https://jsonplaceholder.typicode.com/users"
render={({ list }) => (
<div>
<h2>Random Resources</h2>
<ul>{list.map(resource => <li key={resource.id}>{resource.name}</li>)}</ul>
</div>
)}
/>
);
}
}
Indirection - It is tricky to tell which HOC provides which props.
Naming collisions - Two HOCs that try to use the same prop name will collide and overwrite one another.
Ensure all relevant props are passed through to the component.
It is easy to compose several HOCs together and then this creates a deeply nested tree making it difficult to debug.
Indirection. We don’t have to wonder where our state or props are coming from. We can see them in the render prop’s argument list.
Naming collisions. There is no automatic merging of property names, so there is no chance for a naming collision.
Hooks are functions that lets you "hook" into React internal state and lifecycle features from a function component.
Component has State?
Class Component
Function Component
YES
NO
Can't break down complex components with stateful logic into functions or reusable components.
Common use cases include animations, form handling, connecting to external data sources.
const [count, setCount] = useState(0);
useState, as the name describes, is a hook that allows you to use state in your function.
import React, { useState } from 'react';
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
// Declare multiple state variables!
const [age, setAge] = useState(42);
const [fruit, setFruit] = useState('banana');
const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
const [data, setData] = useState();
useEffect(() => {
const fetchGithubData = async (name) => {
const result = await axios(`https://api.github.com/users/${name}/events`)
setData(result.data)
}
fetchGithubData('rohitkrai03')
}, [data])
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
});
You can combine built-in Hooks provided by React into your own “custom Hooks”.
const ResponsiveComponent = () => {
const width = useWindowWidth();
return (
<p>Window width is {width}</p>
)
}
const useWindowWidth = () => {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
});
return width;
}
Don’t call Hooks inside loops, conditions, or nested functions.