- Dec 2022
-
www.developerway.com www.developerway.com
-
useMemo has its cost (consumes a bit of memory and makes initial render slightly slower)
-
✅ useMemo for expensive calculations
-
If a component uses non-primitive value as a dependency in hooks like useEffect, useMemo, useCallback, it should be memoized.
-
If a child component is wrapped in React.memo, all props that are not primitive values have to be memoized
-
✅ Necessary useMemo/useCallback
<br/>
-
⛔️ Antipattern: unnecessary useMemo/useCallback on props
-
If a parent component re-renders, it will trigger re-render of a child component regardless of its props.
-
Memoizing props by themselves will not prevent re-renders of a child component.
-
React.memo has to be applied to the elements passed as children/props.
-
✅ React.memo: components as props or children
-
All props that are not primitive values have to be memoized for React.memo to work
-
✅ React.memo: component with props
-
Wrapping a component in React.memo will stop the downstream chain of re-renders that is triggered somewhere up the render tree, unless this component’s props have changed.
-
Preventing re-renders with React.memo
-
Props are not affected by the state change, so heavy components won’t re-render
-
encapsulates the state inside a smaller component, and heavy components are passed to it as props
-
✅ Preventing re-renders with composition: components as props
-
✅ Preventing re-renders with composition: children as props
-
✅ Preventing re-renders with composition: moving state down
-
There is also a big myth: that re-renders happen when the component’s props change. By itself, it’s not true (see the explanation below).
-
hooks changes
-
context changes
-
parent (or children) re-renders
-
state changes
-
There are four reasons why a component would re-render itself:
-
- Nov 2022
-
www.aquib.dev www.aquib.dev
Tags
Annotators
URL
-
-
vite-pwa-org.netlify.app vite-pwa-org.netlify.app
-
www.causal.app www.causal.app
-
-
www.developerway.com www.developerway.com
-
www.developerway.com www.developerway.com
-
www.developerway.com www.developerway.com
-
www.developerway.com www.developerway.com
-
maxrozen.com maxrozen.com
Tags
Annotators
URL
-
-
www.nielskrijger.com www.nielskrijger.com
-
github.com github.com
Tags
Annotators
URL
-
-
www.youtube.com www.youtube.com
-
-
Tags
Annotators
URL
-
-
css-tricks.com css-tricks.com
Tags
Annotators
URL
-
-
kabartolo.github.io kabartolo.github.io
-
-
-
legacy.reactjs.org legacy.reactjs.org
Tags
Annotators
URL
-
-
unprogrammer.com unprogrammer.com
-
bvaughn.github.io bvaughn.github.io
-
egghead.io egghead.io
-
remix.run remix.run
Tags
Annotators
URL
-
-
Tags
Annotators
URL
-
- Oct 2022
-
www.developerhandbook.com www.developerhandbook.com
-
dmitripavlutin.com dmitripavlutin.com
Tags
Annotators
URL
-
-
blog.logrocket.com blog.logrocket.com
-
reactrouter.com reactrouter.com
-
twitter.com twitter.com
-
www.infoworld.com www.infoworld.com
-
codesandbox.io codesandbox.io
Tags
Annotators
URL
-
- Sep 2022
-
sebhastian.com sebhastian.com
Tags
Annotators
URL
-
-
sebhastian.com sebhastian.com
Tags
Annotators
URL
-
-
sebhastian.com sebhastian.com
-
Sometimes, Create React App will produce an error when you try to create a new application using npx or npm init.
Create React App no longer support global installation This is how to fix the issue
-
-
blog.jim-nielsen.com blog.jim-nielsen.com
-
tkdodo.eu tkdodo.eu
-
remix.run remix.run
Tags
Annotators
URL
-
-
reactrouter.com reactrouter.com
Tags
Annotators
URL
-
-
reactrouter.com reactrouter.com
Tags
Annotators
URL
-
-
codesandbox.io codesandbox.io
-
```js import { useState } from 'react';
/* * @return {Function} getterSetter / export function useStateFunction(initialValue) { const [state, setState] = useState(initialValue);
return function(...args) { if (args.length === 0) { return state; } return setState(...args); };
} ```
-
-
stackoverflow.com stackoverflow.com
-
```js function App() { const buttonRef = useRef(null); const hookValue = useMyHook(buttonRef.current); const [forceUpdate, setForceUpdate] = useState(false);
return ( <div> <button onClick={() => setForceUpdate(prevState => !prevState)}> Update Component </button> <button ref={buttonRef}>Update Hook</button> {"This is hook returned value: " + hookValue} </div> ); } ```
```js import { useEffect, useState } from "react";
function useMyHook(element) { const [myHookState, setMyHookState] = useState(0);
console.log("Inside useMyhook..."); console.log("This is the element received: " + element);
useEffect(() => { console.log("Inside useMyhook useEffect...");
function onClick() { setMyHookState(prevState => prevState + 1); } if (element !== null) { element.addEventListener("click", onClick); } return () => { console.log("Inside useMyhook useEffect return..."); if (element !== null) { element.removeEventListener("click", onClick); } };
});
return myHookState; }
export default useMyHook; ```
-
-
stackoverflow.com stackoverflow.com
-
refine.dev refine.dev
-
-
paco.me paco.me
-
-
www.youtube.com www.youtube.comYouTube1
-
-
blog.logrocket.com blog.logrocket.com
- Aug 2022
-
stackoverflow.com stackoverflow.com
-
stackoverflow.com stackoverflow.com
-
js useEffect(() => { console.log(outcomes) }, [JSON.stringify(outcomes)]) // 🧐🤯
-
-
blog.logrocket.com blog.logrocket.com
Tags
Annotators
URL
-
-
blog.bitsrc.io blog.bitsrc.io
-
blog.openreplay.com blog.openreplay.com
-
www.youtube.com www.youtube.com
-
-
www.netlify.com www.netlify.com
-
kentcdodds.com kentcdodds.com
-
gaplo917.github.io gaplo917.github.io
-
github.com github.com
-
The current web developmennt ONLY offload the tasks to web worker when the application encounter performance issues but NOT by the tasks' nature.
-
-
Tags
Annotators
URL
-
-
daily-dev-tips.com daily-dev-tips.com
-
And in our case, we want it to keep track of our storage object. So let's also create a usePeristentContext hook.
```js import { useMutation, useQuery, useQueryClient } from 'react-query';
export default function usePersistentContext(key) { const queryClient = useQueryClient();
const { data } = useQuery(key, () => localStorage.getItem(key));
const { mutateAsync: setValue } = useMutation( (value) => localStorage.setItem(key, value), { onMutate: (mutatedData) => { const current = data; queryClient.setQueryData(key, mutatedData); return current; }, onError: (_, __, rollback) => { queryClient.setQueryData(key, rollback); }, } );
return [data, setValue]; } ```
js function SetContext() { const [value, setValue] = usePersistentContext('item_context'); return ( <button onClick={() => setValue(value === 'on' ? 'off' : 'on')}> Click me {value} </button> ); }
-
-
-
No extra re-renders
-
-
attardi.org attardi.org
Tags
Annotators
URL
-
-
www.youtube.com www.youtube.com
-
-
www.joshwcomeau.com www.joshwcomeau.com
Tags
Annotators
URL
-
-
beta.reactjs.org beta.reactjs.org
-
-
Tags
Annotators
URL
-
-
tech.groww.in tech.groww.in
-
levelup.gitconnected.com levelup.gitconnected.com
-
turn regular custom hook into a singleton custom hook
-
-
stackblitz.com stackblitz.com
Tags
Annotators
URL
-
-
-
The clientHeight property returns the inner height of an element in pixels. The property includes padding but excludes borders, margins and horizontal scrollbars.Alternatively, you can use the offsetHeight property, which returns the height of the element in pixels, including vertical padding and borders.
```js useEffect(() => { setDivHeight(ref.current.offsetHeight); console.log('height: ', ref.current.offsetHeight);
console.log('width: ', ref.current.offsetWidth); }, []); ```
Tags
Annotators
URL
-
-
www.youtube.com www.youtube.com
-
-
felixgerschau.com felixgerschau.com
Tags
Annotators
URL
-
-
stackoverflow.com stackoverflow.com
-
```js export function Tweet({ tweetID, }) { const tweetRef = useRef(null); const [isLoading, setIsLoading] = useState(true);
useEffect(() => { const tweetEl = tweetRef?.current if (window.twttr && tweetEl) (async() => { await window.twttr.ready(); await window.twttr.widgets.createTweet( tweetID, tweetEl, { align: 'center', conversation: 'none', dnt: true, } ); setIsLoading(false); console.log('Tweet loaded') })(); return () => { tweetEl?.remove(); } }, [tweetID, tweetRef]);
return ( <div ref={tweetRef} className="w-full bg-gray-100 h-fit animate-fadeIn" id={tweetID}> {isLoading &&
🐦
} </div> ); }; ```
-
-
rahuulmiishra.medium.com rahuulmiishra.medium.com
-
medium.com medium.com
- Jul 2022
-
isamatov.com isamatov.com
Tags
Annotators
URL
-
-
kentcdodds.com kentcdodds.com
Tags
Annotators
URL
-
-
dexie.org dexie.org
-
www.smashingmagazine.com www.smashingmagazine.com
- Jun 2022
-
codesandbox.io codesandbox.io
Tags
Annotators
URL
-
-
www.developerway.com www.developerway.com
-
www.gabe.pizza www.gabe.pizza
Tags
Annotators
URL
-
-
blockprotocol.org blockprotocol.org
Tags
Annotators
URL
-
-
storybook.js.org storybook.js.org
-
-
www.youtube.com www.youtube.com
-
-
reactjs.org reactjs.org
-
-
www.commoninja.com www.commoninja.com
-
techlia.hashnode.dev techlia.hashnode.dev
-
Tags
Annotators
URL
-
-
www.debugbear.com www.debugbear.com
-
-
dev.to dev.to
-
www.youtube.com www.youtube.comYouTube1
-
-
blog.logrocket.com blog.logrocket.com
-
```js import DOMPurify from 'dompurify'
const App = () => { const data =
lorem <b onmouseover="alert('mouseover');">ipsum</b>
const sanitizedData = () => ({ __html: DOMPurify.sanitize(data) })return ( <div dangerouslySetInnerHTML={sanitizedData()} /> ); }
export default App; ```
-
-
alexsidorenko.com alexsidorenko.com
-
It still doesn’t work - every component re-renders. This happens because we put items as a dependency for useCallback . Every time items update, useCallback returns a new reference of the function. This causes onChange prop to change, therefore updating every component in the list. To fix this, we need to stop relying on items as a dependency. We can achieve that with a functional state update:
js const onChange = useCallback((id, value) => { setItems(prevItems => prevItems.map((item, index) => { return index !== id ? item : { value: value } })) }, []) // No dependencies
-
To prevent that, we need to memoize it with useCallback. Let’s do that:
```js const Parent = () => { ...
const onChange = useCallback((id, value) => { setItems(items.map((item, index) => { return index !== id ? item : { value: value } })) }, [items])
return ( <div> {items.map((item, index) => ( <Item key={index} id={index} value={item.value} onChange={onChange} /> )} </div> ) } ```
-
Anonymous functions will always get a new reference on every render. This means that onChange property will change every time Parent renders.
js onChange={(id, value) => setState(state.map((item, index) => { return index !== id ? item : { value: value } })}
-
If you don’t want a component to re-render when its parent renders, wrap it with memo. After that, the component indeed will only re-render when its props change.
js const Item = memo(() => <div>Item</div>)
Tags
Annotators
URL
-
-
alexsidorenko.com alexsidorenko.com
-
alexsidorenko.com alexsidorenko.com
Tags
Annotators
URL
-
-
dev.to dev.to
-
www.smashingmagazine.com www.smashingmagazine.com
- May 2022
-
casesandberg.github.io casesandberg.github.io
Tags
Annotators
URL
-
-
blog.logrocket.com blog.logrocket.com
-
So by applying the key prop on the fragment, our code now looks like this:
```js import React from "react";
// ... const App = () => ( <>
List of all items:
{items.map(({ name, title }, index) => ( <React.Fragment key={index}>{name}
{title}
</React.Fragment> ))} <br /> );export default App; ```
Tags
Annotators
URL
-
-
betterprogramming.pub betterprogramming.pub
-
React Helmet
```js import {Helmet} from "react-helmet";
const Demo = props => ( <br /> <div className="application"> <Helmet> <script src="/path/to/resource.js" type="text/javascript" /> </Helmet> ... </div>
); ```
DOM Method
```js componentDidMount () { const script = document.createElement("script"); script.src = "/path/to/resource.js"; script.async = true; document.body.appendChild(script); }
export const appendScript = (scriptToAppend) => { const script = document.createElement("script"); script.src = scriptToAppend; script.async = true; document.body.appendChild(script); }
class Demo extends React.Component { componentDidMount () { appendScript("/path/to/resource.js"); } } ```
React Hooks
js useEffect(() => { const script = document.createElement('script'); script.src = "/path/to/resource.js"; script.async = true; document.body.appendChild(script); return () => { document.body.removeChild(script); } }, []);
```js import { useEffect } from 'react'; const importScript = resourceUrl=> { useEffect(() => { const script = document.createElement('script'); script.src = resourceUrl; script.async = true; document.body.appendChild(script); return () => { document.body.removeChild(script); } }, [resourceUrl]); };
const Demo = props => { importScript("/path/to/resource.js"); } ```
-
-
usehooks-ts.com usehooks-ts.com
-
-
blog.saeloun.com blog.saeloun.com
-
```js import { useState } from "react"; import "./styles.css";
const VIDEO_LINKS = [ "https://www.sample-videos.com/video123/mp4/240/big_buck_bunny_240p_2mb.mp4", "https://www.sample-videos.com/video123/mp4/480/big_buck_bunny_480p_2mb.mp4", "https://www.sample-videos.com/video123/mp4/720/big_buck_bunny_720p_20mb.mp4" ];
export default function App() { const [switchVideo, setSwitchVideo] = useState(0); const [videoWidth, setVideoWidth] = useState(null); const [videoHeight, setVideoHeight] = useState(null);
return ( <div className="App"> <video src={VIDEO_LINKS[switchVideo]} controls style= onResize={(e) => { setVideoWidth(e.target.videoWidth); setVideoHeight(e.target.videoHeight); }} /> <div className="resButton"> <button onClick={() => setSwitchVideo(0)}>240p</button> <button onClick={() => setSwitchVideo(1)}>480p</button> <button onClick={() => setSwitchVideo(2)}>720p</button> </div> </div> ); } ```
-
-
javascript.plainenglish.io javascript.plainenglish.io
-
```css .long-text { margin-bottom: 10px; }
.clamp { -webkit-line-clamp: 5; -webkit-box-orient: vertical; display: -webkit-box; overflow: hidden; text-overflow: ellipsis; overflow-wrap: break-word; } ```
```js import { LoremIpsum } from "https://cdn.skypack.dev/lorem-ipsum@2.0.3"; import classnames from "https://cdn.skypack.dev/classnames@2.3.1"; import * as lodash from "https://cdn.skypack.dev/lodash@4.17.21";
const getText = (paragraphs) => { const lorem = new LoremIpsum(); return lorem.generateParagraphs(paragraphs); };
const ReadMoreText = ({ text }) => { const [clamped, setClamped] = React.useState(true); const [showButton, setShowButton] = React.useState(true); const containerRef = React.useRef(null); const handleClick = () => setClamped(!clamped);
React.useEffect(() => { const hasClamping = (el) => { const { clientHeight, scrollHeight } = el; return clientHeight !== scrollHeight; };
const checkButtonAvailability = () => { if (containerRef.current) { // Save current state to reapply later if necessary. const hadClampClass = containerRef.current.classList.contains("clamp"); // Make sure that CSS clamping is applied if aplicable. if (!hadClampClass) containerRef.current.classList.add("clamp"); // Check for clamping and show or hide button accordingly. setShowButton(hasClamping(containerRef.current)); // Sync clamping with local state. if (!hadClampClass) containerRef.current.classList.remove("clamp"); } }; const debouncedCheck = lodash.debounce(checkButtonAvailability, 50); checkButtonAvailability(); window.addEventListener("resize", debouncedCheck); return () => { window.removeEventListener("resize", debouncedCheck); };
}, [containerRef]);
return ( <> <div ref={containerRef} className={classnames("long-text", clamped && "clamp")} > {text} </div> {showButton && ( <button onClick={handleClick}>Read {clamped ? "more" : "less"}</button> )} <br /> ); };
const App = () => { const text = getText(2); return <ReadMoreText text={text} />; };
ReactDOM.render(<App />, document.getElementById("App")); ```
-
-
javascript.plainenglish.io javascript.plainenglish.io
-
codesandbox.io codesandbox.io
-
- Apr 2022
-
stackoverflow.com stackoverflow.com
-
css .hoverClassColor:hover { color:var(--hover-color) !important; }
js render() { return <a className={'hoverClassColor'} style={{'--hover-color':'red'}}>Test</a> }
-
-
stackoverflow.com stackoverflow.com
-
```js function useTraceUpdate(props) { const prev = useRef(props); useEffect(() => { const changedProps = Object.entries(props) .reduce((ps, [k, v]) => { if (prev.current[k] !== v) { ps[k] = [prev.current[k], v]; } return ps; }, {}); if (Object.keys(changedProps).length > 0) { console.log('Changed props:', changedProps); } prev.current = props; }); }
// Usage function MyComponent(props) { useTraceUpdate(props); return <div>{props.children}</div>; } ```
-
-
blog.logrocket.com blog.logrocket.com
-
Using SVG as a component
SVGs can be imported and used directly as a React component in your React code. The image is not loaded as a separate file, instead, it’s rendered along the HTML. A sample use-case would look like this:
```js import React from 'react'; import {ReactComponent as ReactLogo} from './logo.svg';
const App = () => { return ( <div className="App"> <ReactLogo /> </div> ); } export default App; ```
Note this approach only works with create-react-app
Tags
Annotators
URL
-
-
www.robinwieruch.de www.robinwieruch.de
Tags
Annotators
URL
-
-
create-react-app.dev create-react-app.dev
-
dmitripavlutin.com dmitripavlutin.com
Tags
Annotators
URL
-
-
thenable.io thenable.io
Tags
Annotators
URL
-
- Mar 2022
-
reactjs.org reactjs.org
-
www.youtube.com www.youtube.com
-
-
www.youtube.com www.youtube.com
-
-
www.youtube.com www.youtube.com
-
-
reactjs.org reactjs.org
Tags
Annotators
URL
-
-
aglowiditsolutions.com aglowiditsolutions.com
-
Hire ReactJS Developers
-
-
nasreddinebacali.info nasreddinebacali.info
Tags
Annotators
URL
-
-
ahooks.js.org ahooks.js.org
-
-
zhenghao.io zhenghao.ioZhenghao1
-
-
www.smashingmagazine.com www.smashingmagazine.com
-
www.sitepoint.com www.sitepoint.com
Tags
Annotators
URL
-
-
betterprogramming.pub betterprogramming.pub
-
-
-
dunglas.fr dunglas.fr
Tags
Annotators
URL
-
-
react-swipeable-views.com react-swipeable-views.com
Tags
Annotators
URL
-
-
swiperjs.com swiperjs.com
-
- Feb 2022
-
github.com github.com
-
js queryClient .getQueryCache() .findAll(['partial', 'key']) .forEach(({ queryKey }) => { queryClient.setQueryData(queryKey, newData) })
-
-
www.telerik.com www.telerik.com
Tags
Annotators
URL
-
-
usehooks.com usehooks.com
-
-
dmitripavlutin.com dmitripavlutin.com
Tags
Annotators
URL
-
-
dhruvnakum.xyz dhruvnakum.xyz
-
hooks.guide hooks.guide
-
Collection of React hooks curated by the community
-
-
typeofnan.dev typeofnan.dev