main 72fa7786f2e5 cached
57 files
29.8 KB
9.2k tokens
46 symbols
1 requests
Download .txt
Repository: alex83130/advanced-react-patterns
Branch: main
Commit: 72fa7786f2e5
Files: 57
Total size: 29.8 KB

Directory structure:
gitextract_uzcte344/

├── .gitignore
├── README.md
├── package.json
├── public/
│   ├── index.html
│   ├── manifest.json
│   └── robots.txt
└── src/
    ├── App.js
    ├── App.test.js
    ├── index.js
    └── patterns/
        ├── compound-component/
        │   ├── Counter.js
        │   ├── Usage.js
        │   ├── components/
        │   │   ├── Count.js
        │   │   ├── Decrement.js
        │   │   ├── Increment.js
        │   │   ├── Label.js
        │   │   ├── index.js
        │   │   └── styles.js
        │   └── useCounterContext.js
        ├── control-props/
        │   ├── Counter.js
        │   ├── Usage.js
        │   ├── components/
        │   │   ├── Count.js
        │   │   ├── Decrement.js
        │   │   ├── Increment.js
        │   │   ├── Label.js
        │   │   ├── index.js
        │   │   └── styles.js
        │   └── useCounterContext.js
        ├── custom-hooks/
        │   ├── Counter.js
        │   ├── Usage.js
        │   ├── components/
        │   │   ├── Count.js
        │   │   ├── Decrement.js
        │   │   ├── Increment.js
        │   │   ├── Label.js
        │   │   ├── index.js
        │   │   └── styles.js
        │   ├── useCounter.js
        │   └── useCounterContext.js
        ├── props-getters/
        │   ├── Counter.js
        │   ├── Usage.js
        │   ├── components/
        │   │   ├── Count.js
        │   │   ├── Decrement.js
        │   │   ├── Increment.js
        │   │   ├── Label.js
        │   │   ├── index.js
        │   │   └── styles.js
        │   ├── useCounter.js
        │   └── useCounterContext.js
        └── state-reducer/
            ├── Counter.js
            ├── Usage.js
            ├── components/
            │   ├── Count.js
            │   ├── Decrement.js
            │   ├── Increment.js
            │   ├── Label.js
            │   ├── index.js
            │   └── styles.js
            ├── useCounter.js
            └── useCounterContext.js

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# production
/build

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*


================================================
FILE: README.md
================================================
# Getting Started with Advanced React Patterns

Repository used within the article : https://javascript.plainenglish.io/5-advanced-react-patterns-a6b7624267a6


## Available Scripts

In the project directory, you can run:

### `npm start`

Runs the app in the development mode.\
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.

The page will reload if you make edits.\
You will also see any lint errors in the console.

### `npm run build`

Builds the app for production to the `build` folder.\
It correctly bundles React in production mode and optimizes the build for the best performance.

The build is minified and the filenames include the hashes.\
Your app is ready to be deployed!

See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.



================================================
FILE: package.json
================================================
{
  "name": "advanced-react-patterns",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@fortawesome/fontawesome-svg-core": "^1.2.35",
    "@fortawesome/free-solid-svg-icons": "^5.15.3",
    "@fortawesome/react-fontawesome": "^0.1.14",
    "react": "^17.0.1",
    "react-dom": "^17.0.1",
    "react-scripts": "4.0.3",
    "styled-components": "^5.2.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}


================================================
FILE: public/index.html
================================================
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <!--
      manifest.json provides metadata used when your web app is installed on a
      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
    -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>React App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  </body>
</html>


================================================
FILE: public/manifest.json
================================================
{
  "short_name": "React App",
  "name": "Create React App Sample",
  "icons": [
    {
      "src": "favicon.ico",
      "sizes": "64x64 32x32 24x24 16x16",
      "type": "image/x-icon"
    },
    {
      "src": "logo192.png",
      "type": "image/png",
      "sizes": "192x192"
    },
    {
      "src": "logo512.png",
      "type": "image/png",
      "sizes": "512x512"
    }
  ],
  "start_url": ".",
  "display": "standalone",
  "theme_color": "#000000",
  "background_color": "#ffffff"
}


================================================
FILE: public/robots.txt
================================================
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:


================================================
FILE: src/App.js
================================================
import React from "react";
import styled from "styled-components";
import { Usage as CompoundComponent } from "./patterns/compound-component/Usage";
import { Usage as ControlProps } from "./patterns/control-props/Usage";
import { Usage as CustomHooks } from "./patterns/custom-hooks/Usage";
import { Usage as PropsGetters } from "./patterns/props-getters/Usage";
import { Usage as StateReducer } from "./patterns/state-reducer/Usage";

import { library } from "@fortawesome/fontawesome-svg-core";
import {
  faPlus,
  faPlusCircle,
  faPlusSquare,
  faMinus,
  faMinusCircle,
  faMinusSquare
} from "@fortawesome/free-solid-svg-icons";
library.add(
  faPlus,
  faPlusCircle,
  faPlusSquare,
  faMinus,
  faMinusCircle,
  faMinusSquare
);

export default function App() {
  return (
    <StyledContainer>
      <StyledTitleContainer>
        <h1>Advanced React Pattern</h1>
      </StyledTitleContainer>

      <StyledPatternContainer>
        <h2>Compound component pattern</h2>
        <CompoundComponent />
      </StyledPatternContainer>

      <StyledPatternContainer>
        <h2>Control props pattern</h2>
        <ControlProps />
      </StyledPatternContainer>

      <StyledPatternContainer>
        <h2>Custom hooks pattern</h2>
        <CustomHooks />
      </StyledPatternContainer>

      <StyledPatternContainer>
        <h2>Props PropsGetters pattern</h2>
        <PropsGetters />
      </StyledPatternContainer>

      <StyledPatternContainer>
        <h2>State reducer Pattern</h2>
        <StateReducer />
      </StyledPatternContainer>
    </StyledContainer>
  );
}

const StyledContainer = styled.div`
  text-align: center;
  font-family: sans-serif;
`;

const StyledTitleContainer = styled.div`
  background-color: #1428a0;
  color: white;
  padding: 35px;

  > h1 {
    margin: 0;
  }
`;

const StyledPatternContainer = styled.div`
  padding: 30px;
  border-bottom: 2px solid #d3d3d3;

  &:last-child {
    border: none;
  }

  > h2 {
    margin-top: 0;
  }
`;


================================================
FILE: src/App.test.js
================================================
import { render, screen } from '@testing-library/react';
import App from './App';

test('renders learn react link', () => {
  render(<App />);
  const linkElement = screen.getByText(/learn react/i);
  expect(linkElement).toBeInTheDocument();
});


================================================
FILE: src/index.js
================================================
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);



================================================
FILE: src/patterns/compound-component/Counter.js
================================================
import React, { useEffect, useRef, useState } from "react";
import styled from "styled-components";
import { CounterProvider } from "./useCounterContext";
import { Count, Label, Decrement, Increment } from "./components";

function Counter({ children, onChange, initialValue = 0 }) {
  const [count, setCount] = useState(initialValue);

  const firstMounded = useRef(true);
  useEffect(() => {
    if (!firstMounded.current) {
      onChange && onChange(count);
    }
    firstMounded.current = false;
  }, [count, onChange]);

  const handleIncrement = () => {
    setCount(count + 1);
  };

  const handleDecrement = () => {
    setCount(Math.max(0, count - 1));
  };

  return (
    <CounterProvider value={{ count, handleIncrement, handleDecrement }}>
      <StyledCounter>{children}</StyledCounter>
    </CounterProvider>
  );
}

const StyledCounter = styled.div`
  display: inline-flex;
  border: 1px solid #17a2b8;
  line-height: 1.5;
  border-radius: 0.25rem;
  overflow: hidden;
`;

Counter.Count = Count;
Counter.Label = Label;
Counter.Increment = Increment;
Counter.Decrement = Decrement;

export { Counter };


================================================
FILE: src/patterns/compound-component/Usage.js
================================================
import React from "react";
import { Counter } from "./Counter";

function Usage() {
  const handleChangeCounter = (count) => {
    console.log("count", count);
  };

  return (
    <Counter onChange={handleChangeCounter}>
      <Counter.Decrement icon="minus" />
      <Counter.Label>Counter</Counter.Label>
      <Counter.Count max={10} />
      <Counter.Increment icon="plus" />
    </Counter>
  );
}

export { Usage };


================================================
FILE: src/patterns/compound-component/components/Count.js
================================================
import React from "react";
import styled from "styled-components";
import { useCounterContext } from "../useCounterContext";

function Count({ max }) {
  const { count } = useCounterContext();

  const hasError = max ? count >= max : false;

  return <StyledCount hasError={hasError}>{count}</StyledCount>;
}

const StyledCount = styled.div`
  background-color: ${({ hasError }) => (hasError ? "#bd2130" : "#17a2b8")};
  color: white;
  padding: 5px 7px;
`;

export { Count };


================================================
FILE: src/patterns/compound-component/components/Decrement.js
================================================
import React from "react";
import { StyledButton } from "./styles.js";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useCounterContext } from "../useCounterContext";

function Decrement({ icon = "minus" }) {
  const { handleDecrement } = useCounterContext();
  return (
    <StyledButton onClick={handleDecrement}>
      <FontAwesomeIcon icon={icon} color="#17a2b8" />
    </StyledButton>
  );
}

export { Decrement };


================================================
FILE: src/patterns/compound-component/components/Increment.js
================================================
import React from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { StyledButton } from "./styles.js";
import { useCounterContext } from "../useCounterContext";

function Increment({ icon = "plus" }) {
  const { handleIncrement } = useCounterContext();
  return (
    <StyledButton onClick={handleIncrement}>
      <FontAwesomeIcon icon={icon} color="#17a2b8" />
    </StyledButton>
  );
}

export { Increment };


================================================
FILE: src/patterns/compound-component/components/Label.js
================================================
import React from "react";
import styled from "styled-components";

function Label({ children }) {
  return <StyledLabel>{children}</StyledLabel>;
}

const StyledLabel = styled.div`
  background-color: #e9ecef;
  color: #495057;
  padding: 5px 7px;
`;

export { Label };


================================================
FILE: src/patterns/compound-component/components/index.js
================================================
export * from "./Count";
export * from "./Decrement";
export * from "./Increment";
export * from "./Label";


================================================
FILE: src/patterns/compound-component/components/styles.js
================================================
import styled from "styled-components";

const StyledButton = styled.button`
  background-color: white;
  border: none;
  &:hover {
    cursor: pointer;
  }
  &:active,
  &:focus {
    outline: none;
  }
`;

export { StyledButton };


================================================
FILE: src/patterns/compound-component/useCounterContext.js
================================================
import React from "react";

const CounterContext = React.createContext(undefined);

function CounterProvider({ children, value }) {
  return (
    <CounterContext.Provider value={value}>{children}</CounterContext.Provider>
  );
}

function useCounterContext() {
  const context = React.useContext(CounterContext);
  if (context === undefined) {
    throw new Error("useCounterContext must be used within a CounterProvider");
  }
  return context;
}

export { CounterProvider, useCounterContext };


================================================
FILE: src/patterns/control-props/Counter.js
================================================
import React, { useState, useRef, useEffect } from "react";
import styled from "styled-components";
import { CounterProvider } from "./useCounterContext";
import { Count, Label, Decrement, Increment } from "./components";

function Counter({ children, value = null, initialValue = 0, onChange }) {
  const [count, setCount] = useState(initialValue);

  const isControlled = value !== null && !!onChange;

  const getCount = () => (isControlled ? value : count);

  const firstMounded = useRef(true);
  useEffect(() => {
    if (!firstMounded.current && !isControlled) {
      onChange && onChange(count);
    }
    firstMounded.current = false;
  }, [count, onChange, isControlled]);

  const handleIncrement = () => {
    handleCountChange(getCount() + 1);
  };

  const handleDecrement = () => {
    handleCountChange(Math.max(0, getCount() - 1));
  };

  const handleCountChange = (newValue) => {
    isControlled ? onChange(newValue) : setCount(newValue);
  };

  return (
    <CounterProvider
      value={{ count: getCount(), handleIncrement, handleDecrement }}
    >
      <StyledCounter>{children}</StyledCounter>
    </CounterProvider>
  );
}

const StyledCounter = styled.div`
  display: inline-flex;
  border: 1px solid #17a2b8;
  line-height: 1.5;
  border-radius: 0.25rem;
  overflow: hidden;
`;

Counter.Count = Count;
Counter.Label = Label;
Counter.Increment = Increment;
Counter.Decrement = Decrement;

export { Counter };


================================================
FILE: src/patterns/control-props/Usage.js
================================================
import React, { useState } from "react";
import { Counter } from "./Counter";

function Usage() {
  const [count, setCount] = useState(0);

  const handleChangeCounter = (newCount) => {
    setCount(newCount);
  };
  return (
    <Counter value={count} onChange={handleChangeCounter}>
      <Counter.Decrement icon={"minus"} />
      <Counter.Label>Counter</Counter.Label>
      <Counter.Count max={10} />
      <Counter.Increment icon={"plus"} />
    </Counter>
  );
}

export { Usage };


================================================
FILE: src/patterns/control-props/components/Count.js
================================================
import React from "react";
import styled from "styled-components";
import { useCounterContext } from "../useCounterContext";

function Count({ max }) {
  const { count } = useCounterContext();

  const hasError = max ? count >= max : false;

  return <StyledCount hasError={hasError}>{count}</StyledCount>;
}

const StyledCount = styled.div`
  background-color: ${({ hasError }) => (hasError ? "#bd2130" : "#17a2b8")};
  color: white;
  padding: 5px 7px;
`;

export { Count };


================================================
FILE: src/patterns/control-props/components/Decrement.js
================================================
import React from "react";
import { StyledButton } from "./styles.js";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useCounterContext } from "../useCounterContext";

function Decrement({ icon = "minus" }) {
  const { handleDecrement } = useCounterContext();
  return (
    <StyledButton onClick={handleDecrement}>
      <FontAwesomeIcon icon={icon} color="#17a2b8" />
    </StyledButton>
  );
}

export { Decrement };


================================================
FILE: src/patterns/control-props/components/Increment.js
================================================
import React from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { StyledButton } from "./styles.js";
import { useCounterContext } from "../useCounterContext";

function Increment({ icon = "plus" }) {
  const { handleIncrement } = useCounterContext();
  return (
    <StyledButton onClick={handleIncrement}>
      <FontAwesomeIcon icon={icon} color="#17a2b8" />
    </StyledButton>
  );
}

export { Increment };


================================================
FILE: src/patterns/control-props/components/Label.js
================================================
import React from "react";
import styled from "styled-components";

function Label({ children }) {
  return <StyledLabel>{children}</StyledLabel>;
}

const StyledLabel = styled.div`
  background-color: #e9ecef;
  color: #495057;
  padding: 5px 7px;
`;

export { Label };


================================================
FILE: src/patterns/control-props/components/index.js
================================================
export * from "./Count";
export * from "./Decrement";
export * from "./Increment";
export * from "./Label";


================================================
FILE: src/patterns/control-props/components/styles.js
================================================
import styled from "styled-components";

const StyledButton = styled.button`
  background-color: white;
  border: none;
  &:hover {
    cursor: pointer;
  }
  &:active,
  &:focus {
    outline: none;
  }
`;

export { StyledButton };


================================================
FILE: src/patterns/control-props/useCounterContext.js
================================================
import React from "react";

const CounterContext = React.createContext(undefined);

function CounterProvider({ children, value }) {
  return (
    <CounterContext.Provider value={value}>{children}</CounterContext.Provider>
  );
}

function useCounterContext() {
  const context = React.useContext(CounterContext);
  if (context === undefined) {
    throw new Error("useCounterContext must be used within a CounterProvider");
  }
  return context;
}

export { CounterProvider, useCounterContext };


================================================
FILE: src/patterns/custom-hooks/Counter.js
================================================
import React, { useRef, useEffect } from "react";
import styled from "styled-components";
import { CounterProvider } from "./useCounterContext";
import { Count, Label, Decrement, Increment } from "./components";

function Counter({ children, value: count, onChange }) {
  const firstMounded = useRef(true);
  useEffect(() => {
    if (!firstMounded.current) {
      onChange && onChange(count);
    }
    firstMounded.current = false;
  }, [count, onChange]);

  return (
    <CounterProvider value={{ count }}>
      <StyledCounter>{children}</StyledCounter>
    </CounterProvider>
  );
}

const StyledCounter = styled.div`
  display: inline-flex;
  border: 1px solid #17a2b8;
  line-height: 1.5;
  border-radius: 0.25rem;
  overflow: hidden;
`;

Counter.Count = Count;
Counter.Label = Label;
Counter.Increment = Increment;
Counter.Decrement = Decrement;

export { Counter };


================================================
FILE: src/patterns/custom-hooks/Usage.js
================================================
import React from "react";
import styled from "styled-components";
import { Counter } from "./Counter";
import { useCounter } from "./useCounter";

function Usage() {
  const { count, handleIncrement, handleDecrement } = useCounter(0);
  const MAX_COUNT = 10;

  const handleClickIncrement = () => {
    //Put your custom logic
    if (count < MAX_COUNT) {
      handleIncrement();
    }
  };

  return (
    <>
      <Counter value={count}>
        <Counter.Decrement
          icon={"minus"}
          onClick={handleDecrement}
          disabled={count === 0}
        />
        <Counter.Label>Counter</Counter.Label>
        <Counter.Count />
        <Counter.Increment
          icon={"plus"}
          onClick={handleClickIncrement}
          disabled={count === MAX_COUNT}
        />
      </Counter>
      <StyledContainer>
        <button onClick={handleClickIncrement} disabled={count === MAX_COUNT}>
          Custom increment btn 1
        </button>
      </StyledContainer>
    </>
  );
}

export { Usage };

const StyledContainer = styled.div`
  margin-top: 20px;
`;


================================================
FILE: src/patterns/custom-hooks/components/Count.js
================================================
import React from "react";
import styled from "styled-components";
import { useCounterContext } from "../useCounterContext";

function Count({ max }) {
  const { count } = useCounterContext();

  const hasError = max ? count > max : false;

  return <StyledCount hasError={hasError}>{count}</StyledCount>;
}

const StyledCount = styled.div`
  background-color: ${({ hasError }) => (hasError ? "#bd2130" : "#17a2b8")};
  color: white;
  padding: 5px 7px;
`;

export { Count };


================================================
FILE: src/patterns/custom-hooks/components/Decrement.js
================================================
import React from "react";
import { StyledButton } from "./styles.js";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";

function Decrement({ icon = "minus", onClick }) {
  return (
    <StyledButton onClick={onClick}>
      <FontAwesomeIcon icon={icon} color="#17a2b8" />
    </StyledButton>
  );
}

export { Decrement };


================================================
FILE: src/patterns/custom-hooks/components/Increment.js
================================================
import React from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { StyledButton } from "./styles.js";

function Increment({ icon = "plus", onClick }) {
  return (
    <StyledButton onClick={onClick}>
      <FontAwesomeIcon icon={icon} color="#17a2b8" />
    </StyledButton>
  );
}

export { Increment };


================================================
FILE: src/patterns/custom-hooks/components/Label.js
================================================
import React from "react";
import styled from "styled-components";

function Label({ children }) {
  return <StyledLabel>{children}</StyledLabel>;
}

const StyledLabel = styled.div`
  background-color: #e9ecef;
  color: #495057;
  padding: 5px 7px;
`;

export { Label };


================================================
FILE: src/patterns/custom-hooks/components/index.js
================================================
export * from "./Count";
export * from "./Decrement";
export * from "./Increment";
export * from "./Label";


================================================
FILE: src/patterns/custom-hooks/components/styles.js
================================================
import styled from "styled-components";

const StyledButton = styled.button`
  background-color: white;
  border: none;
  &:hover {
    cursor: pointer;
  }
  &:active,
  &:focus {
    outline: none;
  }
`;

export { StyledButton };


================================================
FILE: src/patterns/custom-hooks/useCounter.js
================================================
import { useState } from "react";

function useCounter(intialeCount) {
  const [count, setCount] = useState(intialeCount);

  const handleIncrement = () => {
    setCount((prevCount) => prevCount + 1);
  };

  const handleDecrement = () => {
    setCount((prevCount) => Math.max(0, prevCount - 1));
  };

  return { count, handleIncrement, handleDecrement };
}

export { useCounter };


================================================
FILE: src/patterns/custom-hooks/useCounterContext.js
================================================
import React from "react";

const CounterContext = React.createContext(undefined);

function CounterProvider({ children, value }) {
  return (
    <CounterContext.Provider value={value}>{children}</CounterContext.Provider>
  );
}

function useCounterContext() {
  const context = React.useContext(CounterContext);
  if (context === undefined) {
    throw new Error("useCounterContext must be used within a CounterProvider");
  }
  return context;
}

export { CounterProvider, useCounterContext };


================================================
FILE: src/patterns/props-getters/Counter.js
================================================
import React, { useRef, useEffect } from "react";
import styled from "styled-components";
import { CounterProvider } from "./useCounterContext";
import { Count, Label, Decrement, Increment } from "./components";

function Counter({ children, value: count, onChange }) {
  const firstMounded = useRef(true);
  useEffect(() => {
    if (!firstMounded.current) {
      onChange && onChange(count);
    }
    firstMounded.current = false;
  }, [count, onChange]);

  return (
    <CounterProvider value={{ count }}>
      <StyledCounter>{children}</StyledCounter>
    </CounterProvider>
  );
}

const StyledCounter = styled.div`
  display: inline-flex;
  border: 1px solid #17a2b8;
  line-height: 1.5;
  border-radius: 0.25rem;
  overflow: hidden;
`;

Counter.Count = Count;
Counter.Label = Label;
Counter.Increment = Increment;
Counter.Decrement = Decrement;

export { Counter };


================================================
FILE: src/patterns/props-getters/Usage.js
================================================
import React from "react";
import styled from "styled-components";
import { Counter } from "./Counter";
import { useCounter } from "./useCounter";

const MAX_COUNT = 10;

function Usage() {
  const {
    count,
    getCounterProps,
    getIncrementProps,
    getDecrementProps
  } = useCounter({
    initial: 0,
    max: MAX_COUNT
  });

  const handleBtn1Clicked = () => {
    console.log("btn 1 clicked");
  };

  return (
    <>
      <Counter {...getCounterProps()}>
        <Counter.Decrement icon={"minus"} {...getDecrementProps()} />
        <Counter.Label>Counter</Counter.Label>
        <Counter.Count />
        <Counter.Increment icon={"plus"} {...getIncrementProps()} />
      </Counter>
      <StyledContainer>
        <button {...getIncrementProps({ onClick: handleBtn1Clicked })}>
          Custom increment btn 1
        </button>
      </StyledContainer>
      <StyledContainer>
        <button {...getIncrementProps({ disabled: count > MAX_COUNT - 2 })}>
          Custom increment btn 2
        </button>
      </StyledContainer>
    </>
  );
}

export { Usage };

const StyledContainer = styled.div`
  margin-top: 20px;
`;


================================================
FILE: src/patterns/props-getters/components/Count.js
================================================
import React from "react";
import styled from "styled-components";
import { useCounterContext } from "../useCounterContext";

function Count({ max }) {
  const { count } = useCounterContext();

  const hasError = max ? count >= max : false;

  return <StyledCount hasError={hasError}>{count}</StyledCount>;
}

const StyledCount = styled.div`
  background-color: ${({ hasError }) => (hasError ? "#bd2130" : "#17a2b8")};
  color: white;
  padding: 5px 7px;
`;

export { Count };


================================================
FILE: src/patterns/props-getters/components/Decrement.js
================================================
import React from "react";
import { StyledButton } from "./styles.js";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";

function Decrement({ icon = "minus", onClick, ...props }) {
  return (
    <StyledButton onClick={onClick} {...props}>
      <FontAwesomeIcon icon={icon} color="#17a2b8" />
    </StyledButton>
  );
}

export { Decrement };


================================================
FILE: src/patterns/props-getters/components/Increment.js
================================================
import React from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { StyledButton } from "./styles.js";

function Increment({ icon = "plus", onClick, ...props }) {
  return (
    <StyledButton onClick={onClick} {...props}>
      <FontAwesomeIcon icon={icon} color="#17a2b8" />
    </StyledButton>
  );
}

export { Increment };


================================================
FILE: src/patterns/props-getters/components/Label.js
================================================
import React from "react";
import styled from "styled-components";

function Label({ children }) {
  return <StyledLabel>{children}</StyledLabel>;
}

const StyledLabel = styled.div`
  background-color: #e9ecef;
  color: #495057;
  padding: 5px 7px;
`;

export { Label };


================================================
FILE: src/patterns/props-getters/components/index.js
================================================
export * from "./Count";
export * from "./Decrement";
export * from "./Increment";
export * from "./Label";


================================================
FILE: src/patterns/props-getters/components/styles.js
================================================
import styled from "styled-components";

const StyledButton = styled.button`
  background-color: white;
  border: none;
  &:hover {
    cursor: pointer;
  }
  &:active,
  &:focus {
    outline: none;
  }
`;

export { StyledButton };


================================================
FILE: src/patterns/props-getters/useCounter.js
================================================
import { useState } from "react";

//Function which concat all functions together
const callFnsInSequence = (...fns) => (...args) =>
  fns.forEach((fn) => fn && fn(...args));

function useCounter({ initial, max }) {
  const [count, setCount] = useState(initial);

  const handleIncrement = () => {
    setCount((prevCount) => Math.min(prevCount + 1, max));
  };

  const handleDecrement = () => {
    setCount((prevCount) => Math.max(0, prevCount - 1));
  };

  //props getter for 'Counter'
  const getCounterProps = ({ ...otherProps } = {}) => ({
    value: count,
    "aria-valuemax": max,
    "aria-valuemin": 0,
    "aria-valuenow": count,
    ...otherProps
  });

  //props getter for 'Decrement'
  const getDecrementProps = ({ onClick, ...otherProps } = {}) => ({
    onClick: callFnsInSequence(handleDecrement, onClick),
    disabled: count === 0,
    ...otherProps
  });

  //props getter for 'Increment'
  const getIncrementProps = ({ onClick, ...otherProps } = {}) => ({
    onClick: callFnsInSequence(handleIncrement, onClick),
    disabled: count === max,
    ...otherProps
  });

  return {
    count,
    handleIncrement,
    handleDecrement,
    getCounterProps,
    getDecrementProps,
    getIncrementProps
  };
}

export { useCounter };


================================================
FILE: src/patterns/props-getters/useCounterContext.js
================================================
import React from "react";

const CounterContext = React.createContext(undefined);

function CounterProvider({ children, value }) {
  return (
    <CounterContext.Provider value={value}>{children}</CounterContext.Provider>
  );
}

function useCounterContext() {
  const context = React.useContext(CounterContext);
  if (context === undefined) {
    throw new Error("useCounterContext must be used within a CounterProvider");
  }
  return context;
}

export { CounterProvider, useCounterContext };


================================================
FILE: src/patterns/state-reducer/Counter.js
================================================
import React, { useRef, useEffect } from "react";
import styled from "styled-components";
import { CounterProvider } from "./useCounterContext";
import { Count, Label, Decrement, Increment } from "./components";

function Counter({ children, value: count, onChange }) {
  const firstMounded = useRef(true);
  useEffect(() => {
    if (!firstMounded.current) {
      onChange && onChange(count);
    }
    firstMounded.current = false;
  }, [count, onChange]);

  return (
    <CounterProvider value={{ count }}>
      <StyledCounter>{children}</StyledCounter>
    </CounterProvider>
  );
}

const StyledCounter = styled.div`
  display: inline-flex;
  border: 1px solid #17a2b8;
  line-height: 1.5;
  border-radius: 0.25rem;
  overflow: hidden;
`;

Counter.Count = Count;
Counter.Label = Label;
Counter.Increment = Increment;
Counter.Decrement = Decrement;

export { Counter };


================================================
FILE: src/patterns/state-reducer/Usage.js
================================================
import React from "react";
import styled from "styled-components";
import { Counter } from "./Counter";
import { useCounter } from "./useCounter";

const MAX_COUNT = 10;
function Usage() {
  const reducer = (state, action) => {
    switch (action.type) {
      case "decrement":
        return {
          count: Math.max(0, state.count - 2) //The decrement delta was changed for 2 (Default is 1)
        };
      default:
        return useCounter.reducer(state, action);
    }
  };

  const { count, handleDecrement, handleIncrement } = useCounter(
    { initial: 0, max: 10 },
    reducer
  );

  return (
    <>
      <Counter value={count}>
        <Counter.Decrement icon={"minus"} onClick={handleDecrement} />
        <Counter.Label>Counter</Counter.Label>
        <Counter.Count />
        <Counter.Increment icon={"plus"} onClick={handleIncrement} />
      </Counter>
      <StyledContainer>
        <button onClick={handleIncrement} disabled={count === MAX_COUNT}>
          Custom increment btn 1
        </button>
      </StyledContainer>
    </>
  );
}



export { Usage };

const StyledContainer = styled.div`
  margin-top: 20px;
`;


================================================
FILE: src/patterns/state-reducer/components/Count.js
================================================
import React from "react";
import styled from "styled-components";
import { useCounterContext } from "../useCounterContext";

function Count({ max }) {
  const { count } = useCounterContext();

  const hasError = max ? count >= max : false;

  return <StyledCount hasError={hasError}>{count}</StyledCount>;
}

const StyledCount = styled.div`
  background-color: ${({ hasError }) => (hasError ? "#bd2130" : "#17a2b8")};
  color: white;
  padding: 5px 7px;
`;

export { Count };


================================================
FILE: src/patterns/state-reducer/components/Decrement.js
================================================
import React from "react";
import { StyledButton } from "./styles.js";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";

function Decrement({ icon = "minus", onClick, ...props }) {
  return (
    <StyledButton onClick={onClick} {...props}>
      <FontAwesomeIcon icon={icon} color="#17a2b8" />
    </StyledButton>
  );
}

export { Decrement };


================================================
FILE: src/patterns/state-reducer/components/Increment.js
================================================
import React from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { StyledButton } from "./styles.js";

function Increment({ icon = "plus", onClick, ...props }) {
  return (
    <StyledButton onClick={onClick} {...props}>
      <FontAwesomeIcon icon={icon} color="#17a2b8" />
    </StyledButton>
  );
}

export { Increment };


================================================
FILE: src/patterns/state-reducer/components/Label.js
================================================
import React from "react";
import styled from "styled-components";

function Label({ children }) {
  return <StyledLabel>{children}</StyledLabel>;
}

const StyledLabel = styled.div`
  background-color: #e9ecef;
  color: #495057;
  padding: 5px 7px;
`;

export { Label };


================================================
FILE: src/patterns/state-reducer/components/index.js
================================================
export * from "./Count";
export * from "./Decrement";
export * from "./Increment";
export * from "./Label";


================================================
FILE: src/patterns/state-reducer/components/styles.js
================================================
import styled from "styled-components";

const StyledButton = styled.button`
  background-color: white;
  border: none;
  &:hover {
    cursor: pointer;
  }
  &:active,
  &:focus {
    outline: none;
  }
`;

export { StyledButton };


================================================
FILE: src/patterns/state-reducer/useCounter.js
================================================
import { useReducer } from "react";

const internalReducer = ({ count }, { type, payload }) => {
  switch (type) {
    case "increment":
      return {
        count: Math.min(count + 1, payload.max)
      };
    case "decrement":
      return {
        count: Math.max(0, count - 1)
      };
    default:
      throw new Error(`Unhandled action type: ${type}`);
  }
};

function useCounter({ initial, max }, reducer = internalReducer) {
  const [{ count }, dispatch] = useReducer(reducer, { count: initial });

  const handleIncrement = () => {
    dispatch({ type: "increment", payload: { max } });
  };

  const handleDecrement = () => {
    dispatch({ type: "decrement" });
  };

  return {
    count,
    handleIncrement,
    handleDecrement
  };
}

useCounter.reducer = internalReducer;
useCounter.types = {
  increment: "increment",
  decrement: "decrement"
};

export { useCounter };


================================================
FILE: src/patterns/state-reducer/useCounterContext.js
================================================
import React from "react";

const CounterContext = React.createContext(undefined);

function CounterProvider({ children, value }) {
  return (
    <CounterContext.Provider value={value}>{children}</CounterContext.Provider>
  );
}

function useCounterContext() {
  const context = React.useContext(CounterContext);
  if (context === undefined) {
    throw new Error("useCounterContext must be used within a CounterProvider");
  }
  return context;
}

export { CounterProvider, useCounterContext };
Download .txt
gitextract_uzcte344/

├── .gitignore
├── README.md
├── package.json
├── public/
│   ├── index.html
│   ├── manifest.json
│   └── robots.txt
└── src/
    ├── App.js
    ├── App.test.js
    ├── index.js
    └── patterns/
        ├── compound-component/
        │   ├── Counter.js
        │   ├── Usage.js
        │   ├── components/
        │   │   ├── Count.js
        │   │   ├── Decrement.js
        │   │   ├── Increment.js
        │   │   ├── Label.js
        │   │   ├── index.js
        │   │   └── styles.js
        │   └── useCounterContext.js
        ├── control-props/
        │   ├── Counter.js
        │   ├── Usage.js
        │   ├── components/
        │   │   ├── Count.js
        │   │   ├── Decrement.js
        │   │   ├── Increment.js
        │   │   ├── Label.js
        │   │   ├── index.js
        │   │   └── styles.js
        │   └── useCounterContext.js
        ├── custom-hooks/
        │   ├── Counter.js
        │   ├── Usage.js
        │   ├── components/
        │   │   ├── Count.js
        │   │   ├── Decrement.js
        │   │   ├── Increment.js
        │   │   ├── Label.js
        │   │   ├── index.js
        │   │   └── styles.js
        │   ├── useCounter.js
        │   └── useCounterContext.js
        ├── props-getters/
        │   ├── Counter.js
        │   ├── Usage.js
        │   ├── components/
        │   │   ├── Count.js
        │   │   ├── Decrement.js
        │   │   ├── Increment.js
        │   │   ├── Label.js
        │   │   ├── index.js
        │   │   └── styles.js
        │   ├── useCounter.js
        │   └── useCounterContext.js
        └── state-reducer/
            ├── Counter.js
            ├── Usage.js
            ├── components/
            │   ├── Count.js
            │   ├── Decrement.js
            │   ├── Increment.js
            │   ├── Label.js
            │   ├── index.js
            │   └── styles.js
            ├── useCounter.js
            └── useCounterContext.js
Download .txt
SYMBOL INDEX (46 symbols across 39 files)

FILE: src/App.js
  function App (line 27) | function App() {

FILE: src/patterns/compound-component/Counter.js
  function Counter (line 6) | function Counter({ children, onChange, initialValue = 0 }) {

FILE: src/patterns/compound-component/Usage.js
  function Usage (line 4) | function Usage() {

FILE: src/patterns/compound-component/components/Count.js
  function Count (line 5) | function Count({ max }) {

FILE: src/patterns/compound-component/components/Decrement.js
  function Decrement (line 6) | function Decrement({ icon = "minus" }) {

FILE: src/patterns/compound-component/components/Increment.js
  function Increment (line 6) | function Increment({ icon = "plus" }) {

FILE: src/patterns/compound-component/components/Label.js
  function Label (line 4) | function Label({ children }) {

FILE: src/patterns/compound-component/useCounterContext.js
  function CounterProvider (line 5) | function CounterProvider({ children, value }) {
  function useCounterContext (line 11) | function useCounterContext() {

FILE: src/patterns/control-props/Counter.js
  function Counter (line 6) | function Counter({ children, value = null, initialValue = 0, onChange }) {

FILE: src/patterns/control-props/Usage.js
  function Usage (line 4) | function Usage() {

FILE: src/patterns/control-props/components/Count.js
  function Count (line 5) | function Count({ max }) {

FILE: src/patterns/control-props/components/Decrement.js
  function Decrement (line 6) | function Decrement({ icon = "minus" }) {

FILE: src/patterns/control-props/components/Increment.js
  function Increment (line 6) | function Increment({ icon = "plus" }) {

FILE: src/patterns/control-props/components/Label.js
  function Label (line 4) | function Label({ children }) {

FILE: src/patterns/control-props/useCounterContext.js
  function CounterProvider (line 5) | function CounterProvider({ children, value }) {
  function useCounterContext (line 11) | function useCounterContext() {

FILE: src/patterns/custom-hooks/Counter.js
  function Counter (line 6) | function Counter({ children, value: count, onChange }) {

FILE: src/patterns/custom-hooks/Usage.js
  function Usage (line 6) | function Usage() {

FILE: src/patterns/custom-hooks/components/Count.js
  function Count (line 5) | function Count({ max }) {

FILE: src/patterns/custom-hooks/components/Decrement.js
  function Decrement (line 5) | function Decrement({ icon = "minus", onClick }) {

FILE: src/patterns/custom-hooks/components/Increment.js
  function Increment (line 5) | function Increment({ icon = "plus", onClick }) {

FILE: src/patterns/custom-hooks/components/Label.js
  function Label (line 4) | function Label({ children }) {

FILE: src/patterns/custom-hooks/useCounter.js
  function useCounter (line 3) | function useCounter(intialeCount) {

FILE: src/patterns/custom-hooks/useCounterContext.js
  function CounterProvider (line 5) | function CounterProvider({ children, value }) {
  function useCounterContext (line 11) | function useCounterContext() {

FILE: src/patterns/props-getters/Counter.js
  function Counter (line 6) | function Counter({ children, value: count, onChange }) {

FILE: src/patterns/props-getters/Usage.js
  constant MAX_COUNT (line 6) | const MAX_COUNT = 10;
  function Usage (line 8) | function Usage() {

FILE: src/patterns/props-getters/components/Count.js
  function Count (line 5) | function Count({ max }) {

FILE: src/patterns/props-getters/components/Decrement.js
  function Decrement (line 5) | function Decrement({ icon = "minus", onClick, ...props }) {

FILE: src/patterns/props-getters/components/Increment.js
  function Increment (line 5) | function Increment({ icon = "plus", onClick, ...props }) {

FILE: src/patterns/props-getters/components/Label.js
  function Label (line 4) | function Label({ children }) {

FILE: src/patterns/props-getters/useCounter.js
  function useCounter (line 7) | function useCounter({ initial, max }) {

FILE: src/patterns/props-getters/useCounterContext.js
  function CounterProvider (line 5) | function CounterProvider({ children, value }) {
  function useCounterContext (line 11) | function useCounterContext() {

FILE: src/patterns/state-reducer/Counter.js
  function Counter (line 6) | function Counter({ children, value: count, onChange }) {

FILE: src/patterns/state-reducer/Usage.js
  constant MAX_COUNT (line 6) | const MAX_COUNT = 10;
  function Usage (line 7) | function Usage() {

FILE: src/patterns/state-reducer/components/Count.js
  function Count (line 5) | function Count({ max }) {

FILE: src/patterns/state-reducer/components/Decrement.js
  function Decrement (line 5) | function Decrement({ icon = "minus", onClick, ...props }) {

FILE: src/patterns/state-reducer/components/Increment.js
  function Increment (line 5) | function Increment({ icon = "plus", onClick, ...props }) {

FILE: src/patterns/state-reducer/components/Label.js
  function Label (line 4) | function Label({ children }) {

FILE: src/patterns/state-reducer/useCounter.js
  function useCounter (line 18) | function useCounter({ initial, max }, reducer = internalReducer) {

FILE: src/patterns/state-reducer/useCounterContext.js
  function CounterProvider (line 5) | function CounterProvider({ children, value }) {
  function useCounterContext (line 11) | function useCounterContext() {
Condensed preview — 57 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (36K chars).
[
  {
    "path": ".gitignore",
    "chars": 310,
    "preview": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pn"
  },
  {
    "path": "README.md",
    "chars": 838,
    "preview": "# Getting Started with Advanced React Patterns\n\nRepository used within the article : https://javascript.plainenglish.io/"
  },
  {
    "path": "package.json",
    "chars": 785,
    "preview": "{\n  \"name\": \"advanced-react-patterns\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"dependencies\": {\n    \"@fortawesome/fo"
  },
  {
    "path": "public/index.html",
    "chars": 1721,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"icon\" href=\"%PUBLIC_URL%/favicon.i"
  },
  {
    "path": "public/manifest.json",
    "chars": 492,
    "preview": "{\n  \"short_name\": \"React App\",\n  \"name\": \"Create React App Sample\",\n  \"icons\": [\n    {\n      \"src\": \"favicon.ico\",\n     "
  },
  {
    "path": "public/robots.txt",
    "chars": 67,
    "preview": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nDisallow:\n"
  },
  {
    "path": "src/App.js",
    "chars": 1984,
    "preview": "import React from \"react\";\nimport styled from \"styled-components\";\nimport { Usage as CompoundComponent } from \"./pattern"
  },
  {
    "path": "src/App.test.js",
    "chars": 246,
    "preview": "import { render, screen } from '@testing-library/react';\nimport App from './App';\n\ntest('renders learn react link', () ="
  },
  {
    "path": "src/index.js",
    "chars": 198,
    "preview": "import React from 'react';\nimport ReactDOM from 'react-dom';\nimport App from './App';\n\nReactDOM.render(\n  <React.StrictM"
  },
  {
    "path": "src/patterns/compound-component/Counter.js",
    "chars": 1121,
    "preview": "import React, { useEffect, useRef, useState } from \"react\";\nimport styled from \"styled-components\";\nimport { CounterProv"
  },
  {
    "path": "src/patterns/compound-component/Usage.js",
    "chars": 422,
    "preview": "import React from \"react\";\nimport { Counter } from \"./Counter\";\n\nfunction Usage() {\n  const handleChangeCounter = (count"
  },
  {
    "path": "src/patterns/compound-component/components/Count.js",
    "chars": 477,
    "preview": "import React from \"react\";\nimport styled from \"styled-components\";\nimport { useCounterContext } from \"../useCounterConte"
  },
  {
    "path": "src/patterns/compound-component/components/Decrement.js",
    "chars": 448,
    "preview": "import React from \"react\";\nimport { StyledButton } from \"./styles.js\";\nimport { FontAwesomeIcon } from \"@fortawesome/rea"
  },
  {
    "path": "src/patterns/compound-component/components/Increment.js",
    "chars": 447,
    "preview": "import React from \"react\";\nimport { FontAwesomeIcon } from \"@fortawesome/react-fontawesome\";\nimport { StyledButton } fro"
  },
  {
    "path": "src/patterns/compound-component/components/Label.js",
    "chars": 271,
    "preview": "import React from \"react\";\nimport styled from \"styled-components\";\n\nfunction Label({ children }) {\n  return <StyledLabel"
  },
  {
    "path": "src/patterns/compound-component/components/index.js",
    "chars": 108,
    "preview": "export * from \"./Count\";\nexport * from \"./Decrement\";\nexport * from \"./Increment\";\nexport * from \"./Label\";\n"
  },
  {
    "path": "src/patterns/compound-component/components/styles.js",
    "chars": 233,
    "preview": "import styled from \"styled-components\";\n\nconst StyledButton = styled.button`\n  background-color: white;\n  border: none;\n"
  },
  {
    "path": "src/patterns/compound-component/useCounterContext.js",
    "chars": 497,
    "preview": "import React from \"react\";\n\nconst CounterContext = React.createContext(undefined);\n\nfunction CounterProvider({ children,"
  },
  {
    "path": "src/patterns/control-props/Counter.js",
    "chars": 1439,
    "preview": "import React, { useState, useRef, useEffect } from \"react\";\nimport styled from \"styled-components\";\nimport { CounterProv"
  },
  {
    "path": "src/patterns/control-props/Usage.js",
    "chars": 489,
    "preview": "import React, { useState } from \"react\";\nimport { Counter } from \"./Counter\";\n\nfunction Usage() {\n  const [count, setCou"
  },
  {
    "path": "src/patterns/control-props/components/Count.js",
    "chars": 477,
    "preview": "import React from \"react\";\nimport styled from \"styled-components\";\nimport { useCounterContext } from \"../useCounterConte"
  },
  {
    "path": "src/patterns/control-props/components/Decrement.js",
    "chars": 448,
    "preview": "import React from \"react\";\nimport { StyledButton } from \"./styles.js\";\nimport { FontAwesomeIcon } from \"@fortawesome/rea"
  },
  {
    "path": "src/patterns/control-props/components/Increment.js",
    "chars": 447,
    "preview": "import React from \"react\";\nimport { FontAwesomeIcon } from \"@fortawesome/react-fontawesome\";\nimport { StyledButton } fro"
  },
  {
    "path": "src/patterns/control-props/components/Label.js",
    "chars": 271,
    "preview": "import React from \"react\";\nimport styled from \"styled-components\";\n\nfunction Label({ children }) {\n  return <StyledLabel"
  },
  {
    "path": "src/patterns/control-props/components/index.js",
    "chars": 108,
    "preview": "export * from \"./Count\";\nexport * from \"./Decrement\";\nexport * from \"./Increment\";\nexport * from \"./Label\";\n"
  },
  {
    "path": "src/patterns/control-props/components/styles.js",
    "chars": 233,
    "preview": "import styled from \"styled-components\";\n\nconst StyledButton = styled.button`\n  background-color: white;\n  border: none;\n"
  },
  {
    "path": "src/patterns/control-props/useCounterContext.js",
    "chars": 497,
    "preview": "import React from \"react\";\n\nconst CounterContext = React.createContext(undefined);\n\nfunction CounterProvider({ children,"
  },
  {
    "path": "src/patterns/custom-hooks/Counter.js",
    "chars": 877,
    "preview": "import React, { useRef, useEffect } from \"react\";\nimport styled from \"styled-components\";\nimport { CounterProvider } fro"
  },
  {
    "path": "src/patterns/custom-hooks/Usage.js",
    "chars": 1081,
    "preview": "import React from \"react\";\nimport styled from \"styled-components\";\nimport { Counter } from \"./Counter\";\nimport { useCoun"
  },
  {
    "path": "src/patterns/custom-hooks/components/Count.js",
    "chars": 476,
    "preview": "import React from \"react\";\nimport styled from \"styled-components\";\nimport { useCounterContext } from \"../useCounterConte"
  },
  {
    "path": "src/patterns/custom-hooks/components/Decrement.js",
    "chars": 340,
    "preview": "import React from \"react\";\nimport { StyledButton } from \"./styles.js\";\nimport { FontAwesomeIcon } from \"@fortawesome/rea"
  },
  {
    "path": "src/patterns/custom-hooks/components/Increment.js",
    "chars": 339,
    "preview": "import React from \"react\";\nimport { FontAwesomeIcon } from \"@fortawesome/react-fontawesome\";\nimport { StyledButton } fro"
  },
  {
    "path": "src/patterns/custom-hooks/components/Label.js",
    "chars": 271,
    "preview": "import React from \"react\";\nimport styled from \"styled-components\";\n\nfunction Label({ children }) {\n  return <StyledLabel"
  },
  {
    "path": "src/patterns/custom-hooks/components/index.js",
    "chars": 108,
    "preview": "export * from \"./Count\";\nexport * from \"./Decrement\";\nexport * from \"./Increment\";\nexport * from \"./Label\";\n"
  },
  {
    "path": "src/patterns/custom-hooks/components/styles.js",
    "chars": 233,
    "preview": "import styled from \"styled-components\";\n\nconst StyledButton = styled.button`\n  background-color: white;\n  border: none;\n"
  },
  {
    "path": "src/patterns/custom-hooks/useCounter.js",
    "chars": 385,
    "preview": "import { useState } from \"react\";\n\nfunction useCounter(intialeCount) {\n  const [count, setCount] = useState(intialeCount"
  },
  {
    "path": "src/patterns/custom-hooks/useCounterContext.js",
    "chars": 497,
    "preview": "import React from \"react\";\n\nconst CounterContext = React.createContext(undefined);\n\nfunction CounterProvider({ children,"
  },
  {
    "path": "src/patterns/props-getters/Counter.js",
    "chars": 877,
    "preview": "import React, { useRef, useEffect } from \"react\";\nimport styled from \"styled-components\";\nimport { CounterProvider } fro"
  },
  {
    "path": "src/patterns/props-getters/Usage.js",
    "chars": 1143,
    "preview": "import React from \"react\";\nimport styled from \"styled-components\";\nimport { Counter } from \"./Counter\";\nimport { useCoun"
  },
  {
    "path": "src/patterns/props-getters/components/Count.js",
    "chars": 477,
    "preview": "import React from \"react\";\nimport styled from \"styled-components\";\nimport { useCounterContext } from \"../useCounterConte"
  },
  {
    "path": "src/patterns/props-getters/components/Decrement.js",
    "chars": 361,
    "preview": "import React from \"react\";\nimport { StyledButton } from \"./styles.js\";\nimport { FontAwesomeIcon } from \"@fortawesome/rea"
  },
  {
    "path": "src/patterns/props-getters/components/Increment.js",
    "chars": 360,
    "preview": "import React from \"react\";\nimport { FontAwesomeIcon } from \"@fortawesome/react-fontawesome\";\nimport { StyledButton } fro"
  },
  {
    "path": "src/patterns/props-getters/components/Label.js",
    "chars": 271,
    "preview": "import React from \"react\";\nimport styled from \"styled-components\";\n\nfunction Label({ children }) {\n  return <StyledLabel"
  },
  {
    "path": "src/patterns/props-getters/components/index.js",
    "chars": 108,
    "preview": "export * from \"./Count\";\nexport * from \"./Decrement\";\nexport * from \"./Increment\";\nexport * from \"./Label\";\n"
  },
  {
    "path": "src/patterns/props-getters/components/styles.js",
    "chars": 233,
    "preview": "import styled from \"styled-components\";\n\nconst StyledButton = styled.button`\n  background-color: white;\n  border: none;\n"
  },
  {
    "path": "src/patterns/props-getters/useCounter.js",
    "chars": 1254,
    "preview": "import { useState } from \"react\";\n\n//Function which concat all functions together\nconst callFnsInSequence = (...fns) => "
  },
  {
    "path": "src/patterns/props-getters/useCounterContext.js",
    "chars": 497,
    "preview": "import React from \"react\";\n\nconst CounterContext = React.createContext(undefined);\n\nfunction CounterProvider({ children,"
  },
  {
    "path": "src/patterns/state-reducer/Counter.js",
    "chars": 877,
    "preview": "import React, { useRef, useEffect } from \"react\";\nimport styled from \"styled-components\";\nimport { CounterProvider } fro"
  },
  {
    "path": "src/patterns/state-reducer/Usage.js",
    "chars": 1147,
    "preview": "import React from \"react\";\nimport styled from \"styled-components\";\nimport { Counter } from \"./Counter\";\nimport { useCoun"
  },
  {
    "path": "src/patterns/state-reducer/components/Count.js",
    "chars": 477,
    "preview": "import React from \"react\";\nimport styled from \"styled-components\";\nimport { useCounterContext } from \"../useCounterConte"
  },
  {
    "path": "src/patterns/state-reducer/components/Decrement.js",
    "chars": 361,
    "preview": "import React from \"react\";\nimport { StyledButton } from \"./styles.js\";\nimport { FontAwesomeIcon } from \"@fortawesome/rea"
  },
  {
    "path": "src/patterns/state-reducer/components/Increment.js",
    "chars": 360,
    "preview": "import React from \"react\";\nimport { FontAwesomeIcon } from \"@fortawesome/react-fontawesome\";\nimport { StyledButton } fro"
  },
  {
    "path": "src/patterns/state-reducer/components/Label.js",
    "chars": 271,
    "preview": "import React from \"react\";\nimport styled from \"styled-components\";\n\nfunction Label({ children }) {\n  return <StyledLabel"
  },
  {
    "path": "src/patterns/state-reducer/components/index.js",
    "chars": 108,
    "preview": "export * from \"./Count\";\nexport * from \"./Decrement\";\nexport * from \"./Increment\";\nexport * from \"./Label\";\n"
  },
  {
    "path": "src/patterns/state-reducer/components/styles.js",
    "chars": 233,
    "preview": "import styled from \"styled-components\";\n\nconst StyledButton = styled.button`\n  background-color: white;\n  border: none;\n"
  },
  {
    "path": "src/patterns/state-reducer/useCounter.js",
    "chars": 892,
    "preview": "import { useReducer } from \"react\";\n\nconst internalReducer = ({ count }, { type, payload }) => {\n  switch (type) {\n    c"
  },
  {
    "path": "src/patterns/state-reducer/useCounterContext.js",
    "chars": 497,
    "preview": "import React from \"react\";\n\nconst CounterContext = React.createContext(undefined);\n\nfunction CounterProvider({ children,"
  }
]

About this extraction

This page contains the full source code of the alex83130/advanced-react-patterns GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 57 files (29.8 KB), approximately 9.2k tokens, and a symbol index with 46 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!