558 Matching Annotations
  1. Dec 2022
  2. Nov 2022
  3. Oct 2022
  4. Sep 2022
    1. 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

    1. ```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);
      };
      

      } ```

    1. ```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; ```

  5. Aug 2022
    1. 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> ); }

    1. 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); }, []); ```

    1. ```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> ); }; ```

  6. Jul 2022
  7. Jun 2022
    1. 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

    2. 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> ) } ```

    3. 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 } })}

    4. 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>)

  8. May 2022
    1. 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; ```

    1. 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"); } ```

    1. ```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> ); } ```

    1. ```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")); ```

  9. Apr 2022
    1. ```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>; } ```

    1. 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

  10. Mar 2022
  11. Feb 2022

    Tags

    Annotators

    URL