CopyPastor

Detecting plagiarism made easy.

Score: 1; Reported for: Exact paragraph match Open both answers

Possible Plagiarism

Plagiarized on 2024-10-20
by Ori Drori

Original Post

Original - Posted on 2021-07-24
by Mohamed E.



            
Present in both answers; Present only in the new answer; Present only in the old answer;

Remove the `resultantColors` state, and calculate it whenever `search` changes:
<!-- begin snippet: js hide: false console: true babel: true babelPresetReact: true babelPresetTS: false -->
<!-- language: lang-js -->
const { useMemo, useState } = React;
const mockColors = ['white', 'blue', 'yellow', 'green', 'orange', 'purple'];
function App() { const [search, setSearch] = useState('');
const handleInputChange = (e) => { setSearch(e.target.value); }; const resultantColors = useMemo(() => search == '' ? mockColors : mockColors.filter(color => color.toLowerCase().includes(search.toLowerCase()) ) , [search]);
return ( <div style={{ border: '1px solid blue', padding: 20, margin: 20 }}> Filter Example with UseEffect <br /> <label htmlFor="colors">Filter Color:</label> <input type="search" name="search" value={search} id="colors" onChange={handleInputChange} placeholder="filter colors" /> {resultantColors.length > 0 ? ( resultantColors.map((value, index) => ( <> <li key={`${value} + ${index}`}>{value}</li> </> )) ) : ( <p>No items - search existing value </p> )} </div> ); }
ReactDOM .createRoot(root) .render(<App />);
<!-- language: lang-html -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.3.1/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.3.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>
<!-- end snippet -->

The simplest and most effective way is to not use `useRef` at all. Just use a **callback ref** that creates a new array of refs on every render.
```js function useArrayRef() { const refs = [] return [refs, el => el && refs.push(el)] } ```
### Demo
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-html -->
<div id="root"></div>
<script type="text/babel" defer> const { useEffect, useState } = React
function useArrayRef() { const refs = [] return [refs, el => el && refs.push(el)] }
const App = () => { const [elements, ref] = useArrayRef() const [third, setThird] = useState(false) useEffect(() => { console.log(elements) }, [third])
return ( <div> <div ref={ref}> <button ref={ref} onClick={() => setThird(!third)}>toggle third div</button> </div> <div ref={ref}>another div</div> { third && <div ref={ref}>third div</div>} </div> ); }
ReactDOM.render(<App />, document.getElementById("root")); </script>
<script src="https://unpkg.com/@babel/standalone@7/babel.min.js"></script> <script src="https://unpkg.com/react@17/umd/react.production.min.js"></script> <script src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
<!-- end snippet -->
### Update: Here is a Typescript version of the hook that creates memoized callback refs and supports passing a custom key to each element ref.
```typescript import { MutableRefObject, useRef } from 'react'
type UseElementsRefResult<T extends HTMLElement = HTMLElement> = [ /** * Map of DOM node refs identified by an auto-created key or custom one. */ MutableRefObject<{ readonly [K: string | number]: T }>,
/** * Creates a memoized callback ref for a DOM node. * If you expect the rendering order of nodes to change, use a custom key. * * @param customKey Key used to set/unset the node ref. */ (customKey?: string | number) => (el?: T) => void, ]
/** * Hook that creates callback refs to manage DOM node refs of multiple elements. * Ensures refs remain stable even with re-renders. Use custom keys if the rendering order may change. */ export const useElementsRef = <T extends HTMLElement = HTMLElement>(): UseElementsRefResult<T> => { const elementRefs = useRef({ current: {} as { [K: string | number]: T }, callbacks: {} as Record<string | number, (el?: T) => void>, })
// Resets index on every render; stable refs as long as the render order remains unchanged let currentIndex = 0
return [ elementRefs.current, (customKey) => { const { current: elements, callbacks } = elementRefs.current const autoKey = currentIndex++ const key = customKey ?? autoKey
// Memoize callback for stable ref assignment if (!callbacks[key]) { callbacks[key] = (el) => { // React is setting the ref for this node if (el != null) { elements[key] = el return }
// React is clearing the node ref delete elements[key] } }
return callbacks[key] }, ] } ```
### Demo
<!-- begin snippet: js hide: false console: true babel: true babelPresetReact: true babelPresetTS: true -->
<!-- language: lang-js -->
const { render } = ReactDOM const { useEffect, useRef, useState } = React
const useElementsRef = () => { const elementRefs = useRef({ current: {}, callbacks: {}, })
let currentIndex = 0
return [ elementRefs.current, (customKey) => { const { current: elements, callbacks } = elementRefs.current const autoKey = currentIndex++ const key = customKey ?? autoKey
// Memoize callback for stable ref assignment if (!callbacks[key]) { callbacks[key] = (el) => { // React is setting the ref for this node if (el != null) { elements[key] = el return }
// React is clearing the node ref delete elements[key] } }
return callbacks[key] }, ] }
const App = () => { const [elementsRef, createElementRef] = useElementsRef() const [third, setThird] = useState(false)
useEffect(() => { console.log(elementsRef.current) }, [third])
return ( <div> <div ref={createElementRef()}> <button ref={createElementRef()} onClick={() => setThird(!third)}>toggle third div</button> </div> <div ref={createElementRef('custom-key')}>another div</div> { third && <div ref={createElementRef('third-div')}>third div</div>} </div> ); }
render(<App />, document.getElementById("root"))
<!-- language: lang-html -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.3.1/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.3.1/umd/react-dom.production.min.js"></script> <div id="root"></div>
<!-- end snippet -->


        
Present in both answers; Present only in the new answer; Present only in the old answer;