├── 7_ROUTER
└── router
│ ├── src
│ ├── components
│ │ ├── Navbar.css
│ │ ├── Search.jsx
│ │ └── Navbar.jsx
│ ├── routes
│ │ ├── Contact.jsx
│ │ ├── Info.jsx
│ │ ├── ErrorPage.jsx
│ │ ├── Search.jsx
│ │ ├── Product.jsx
│ │ └── Home.jsx
│ ├── App.jsx
│ ├── App.css
│ ├── index.css
│ ├── main.jsx
│ ├── hooks
│ │ └── useFetch.js
│ └── assets
│ │ └── react.svg
│ ├── vite.config.js
│ ├── .gitignore
│ ├── index.html
│ ├── package.json
│ ├── data
│ └── db.json
│ └── public
│ └── vite.svg
├── 4_CSS_REACT
└── css
│ ├── src
│ ├── components
│ │ ├── MyComponent.css
│ │ ├── Title.module.css
│ │ ├── Title.jsx
│ │ └── MyComponent.jsx
│ ├── index.css
│ ├── main.jsx
│ ├── App.css
│ ├── App.jsx
│ └── assets
│ │ └── react.svg
│ ├── vite.config.js
│ ├── .gitignore
│ ├── index.html
│ ├── package.json
│ └── public
│ └── vite.svg
├── 3_AVANCANDO_EM_REACT
└── avancando
│ ├── public
│ ├── img.jpg
│ └── vite.svg
│ ├── src
│ ├── assets
│ │ ├── night.jpg
│ │ └── react.svg
│ ├── components
│ │ ├── MessageState.jsx
│ │ ├── ShowUserName.jsx
│ │ ├── ExecuteFunction.jsx
│ │ ├── Container.jsx
│ │ ├── Fragment.jsx
│ │ ├── CarDetails.jsx
│ │ ├── ChangeMessageState.jsx
│ │ ├── Data.jsx
│ │ ├── ConditionalRender.jsx
│ │ └── ListRender.jsx
│ ├── main.jsx
│ ├── App.css
│ ├── index.css
│ └── App.jsx
│ ├── vite.config.js
│ ├── .gitignore
│ ├── index.html
│ └── package.json
├── 1_INTRO
└── intro
│ ├── vite.config.js
│ ├── src
│ ├── main.jsx
│ ├── App.jsx
│ ├── App.css
│ ├── index.css
│ └── assets
│ │ └── react.svg
│ ├── .gitignore
│ ├── index.html
│ ├── package.json
│ └── public
│ └── vite.svg
├── 5_FORM_REACT
└── form
│ ├── vite.config.js
│ ├── src
│ ├── components
│ │ ├── MyForm.css
│ │ └── MyForm.jsx
│ ├── main.jsx
│ ├── App.jsx
│ ├── App.css
│ ├── index.css
│ └── assets
│ │ └── react.svg
│ ├── .gitignore
│ ├── index.html
│ ├── package.json
│ └── public
│ └── vite.svg
├── 6_HTTP_REACT
└── http
│ ├── vite.config.js
│ ├── src
│ ├── main.jsx
│ ├── App.css
│ ├── index.css
│ ├── App.jsx
│ └── assets
│ │ └── react.svg
│ ├── .gitignore
│ ├── index.html
│ ├── package.json
│ ├── public
│ └── vite.svg
│ ├── hooks
│ └── useFetch.js
│ └── data
│ └── db.json
├── 9_HOOKS
└── hooks
│ ├── vite.config.js
│ ├── src
│ ├── hooks
│ │ └── usePrevious.jsx
│ ├── components
│ │ ├── HookUseContext.jsx
│ │ ├── List.jsx
│ │ ├── HookUseImperativeHandle.jsx
│ │ ├── HookCustom.jsx
│ │ ├── HookUseCallback.jsx
│ │ ├── HookUseLayoutEffect.jsx
│ │ ├── SomeComponent.jsx
│ │ ├── HookUseMemo.jsx
│ │ ├── HookUseState.jsx
│ │ ├── HookUseRef.jsx
│ │ ├── HookUseEffect.jsx
│ │ └── HookUseReducer.jsx
│ ├── routes
│ │ ├── Contact.jsx
│ │ └── Home.jsx
│ ├── App.jsx
│ ├── App.css
│ ├── main.jsx
│ ├── index.css
│ └── assets
│ │ └── react.svg
│ ├── .gitignore
│ ├── index.html
│ ├── package.json
│ └── public
│ └── vite.svg
├── 8_CONTEXT_API
└── context
│ ├── vite.config.js
│ ├── src
│ ├── components
│ │ ├── Navbar.jsx
│ │ └── ChangeCounter.jsx
│ ├── hooks
│ │ ├── useTitleColorContext.jsx
│ │ └── useCounterContext.jsx
│ ├── App.jsx
│ ├── context
│ │ ├── CounterContext.jsx
│ │ └── TitleColorContext.jsx
│ ├── routes
│ │ ├── Contact.jsx
│ │ └── Home.jsx
│ ├── App.css
│ ├── main.jsx
│ ├── index.css
│ └── assets
│ │ └── react.svg
│ ├── .gitignore
│ ├── index.html
│ ├── package.json
│ └── public
│ └── vite.svg
└── 2_FUNDAMENTOS
└── fundamentos_react
├── vite.config.js
├── src
├── components
│ ├── MyComponent.jsx
│ ├── FirstComponent.jsx
│ ├── TemplateExpression.jsx
│ └── Events.jsx
├── main.jsx
├── App.css
├── App.jsx
├── index.css
└── assets
│ └── react.svg
├── .gitignore
├── index.html
├── package.json
└── public
└── vite.svg
/7_ROUTER/router/src/components/Navbar.css:
--------------------------------------------------------------------------------
1 | .active {
2 | background-color: red;
3 | color: #000;
4 | }
5 |
--------------------------------------------------------------------------------
/4_CSS_REACT/css/src/components/MyComponent.css:
--------------------------------------------------------------------------------
1 | p {
2 | color: green;
3 | border-bottom: 1px solid #000;
4 | }
5 |
--------------------------------------------------------------------------------
/4_CSS_REACT/css/src/components/Title.module.css:
--------------------------------------------------------------------------------
1 | .title {
2 | color: orange;
3 | background-color: #000;
4 | padding: 10px;
5 | }
6 |
--------------------------------------------------------------------------------
/3_AVANCANDO_EM_REACT/avancando/public/img.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matheusbattisti/react_completo/HEAD/3_AVANCANDO_EM_REACT/avancando/public/img.jpg
--------------------------------------------------------------------------------
/3_AVANCANDO_EM_REACT/avancando/src/assets/night.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matheusbattisti/react_completo/HEAD/3_AVANCANDO_EM_REACT/avancando/src/assets/night.jpg
--------------------------------------------------------------------------------
/1_INTRO/intro/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()]
7 | })
8 |
--------------------------------------------------------------------------------
/4_CSS_REACT/css/src/components/Title.jsx:
--------------------------------------------------------------------------------
1 | import styles from "./Title.module.css";
2 |
3 | const Title = () => {
4 | return
Meu título!
;
5 | };
6 |
7 | export default Title;
8 |
--------------------------------------------------------------------------------
/4_CSS_REACT/css/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()]
7 | })
8 |
--------------------------------------------------------------------------------
/5_FORM_REACT/form/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()]
7 | })
8 |
--------------------------------------------------------------------------------
/6_HTTP_REACT/http/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()]
7 | })
8 |
--------------------------------------------------------------------------------
/7_ROUTER/router/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()]
7 | })
8 |
--------------------------------------------------------------------------------
/9_HOOKS/hooks/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | })
8 |
--------------------------------------------------------------------------------
/8_CONTEXT_API/context/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | })
8 |
--------------------------------------------------------------------------------
/2_FUNDAMENTOS/fundamentos_react/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()]
7 | })
8 |
--------------------------------------------------------------------------------
/3_AVANCANDO_EM_REACT/avancando/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()]
7 | })
8 |
--------------------------------------------------------------------------------
/5_FORM_REACT/form/src/components/MyForm.css:
--------------------------------------------------------------------------------
1 | form {
2 | width: 500px;
3 | margin: 0 auto;
4 | text-align: left;
5 | }
6 |
7 | input,
8 | textarea,
9 | select {
10 | display: block;
11 | margin-top: 10px;
12 | }
13 |
--------------------------------------------------------------------------------
/3_AVANCANDO_EM_REACT/avancando/src/components/MessageState.jsx:
--------------------------------------------------------------------------------
1 | const MessageState = ({ msg }) => {
2 | return (
3 |
4 |
A mensagem é: {msg}
5 |
6 | );
7 | };
8 |
9 | export default MessageState;
10 |
--------------------------------------------------------------------------------
/7_ROUTER/router/src/routes/Contact.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | const Contact = () => {
4 | return (
5 |
6 |
Página de contato
7 |
8 | );
9 | };
10 |
11 | export default Contact;
12 |
--------------------------------------------------------------------------------
/2_FUNDAMENTOS/fundamentos_react/src/components/MyComponent.jsx:
--------------------------------------------------------------------------------
1 | const MyComponent = () => {
2 | return (
3 |
4 |
Eu estou em vários componentes!
5 |
6 | );
7 | };
8 |
9 | export default MyComponent;
10 |
--------------------------------------------------------------------------------
/3_AVANCANDO_EM_REACT/avancando/src/components/ShowUserName.jsx:
--------------------------------------------------------------------------------
1 | const ShowUserName = (props) => {
2 | return (
3 |
4 |
O nome do usuário é: {props.name}
5 |
6 | );
7 | };
8 |
9 | export default ShowUserName;
10 |
--------------------------------------------------------------------------------
/9_HOOKS/hooks/src/hooks/usePrevious.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useRef } from "react";
2 |
3 | export const usePrevious = (value) => {
4 | const ref = useRef;
5 |
6 | useEffect(() => {
7 | ref.current = value;
8 | });
9 |
10 | return ref.current;
11 | };
12 |
--------------------------------------------------------------------------------
/3_AVANCANDO_EM_REACT/avancando/src/components/ExecuteFunction.jsx:
--------------------------------------------------------------------------------
1 | const ExecuteFunction = ({ myFunction }) => {
2 | return (
3 |
4 |
5 |
6 | );
7 | };
8 |
9 | export default ExecuteFunction;
10 |
--------------------------------------------------------------------------------
/4_CSS_REACT/css/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: Helvetica;
5 | padding-bottom: 500px;
6 | }
7 |
8 | h1 {
9 | color: red;
10 | }
11 |
12 | /* classes dinamicas */
13 | .red-title {
14 | font-size: 50px;
15 | color: red;
16 | }
17 |
--------------------------------------------------------------------------------
/1_INTRO/intro/src/main.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom/client'
3 | import App from './App'
4 | import './index.css'
5 |
6 | ReactDOM.createRoot(document.getElementById('root')).render(
7 |
8 |
9 |
10 | )
11 |
--------------------------------------------------------------------------------
/3_AVANCANDO_EM_REACT/avancando/src/components/Container.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | const Container = ({ children }) => {
4 | return (
5 |
6 |
Conteúdo do componente pai:
7 | {children}
8 |
9 | );
10 | };
11 |
12 | export default Container;
13 |
--------------------------------------------------------------------------------
/4_CSS_REACT/css/src/components/MyComponent.jsx:
--------------------------------------------------------------------------------
1 | import "./MyComponent.css";
2 |
3 | const MyComponent = () => {
4 | return (
5 |
6 |
CSS de componente
7 |
Este parágrafo vai ter um estilo
8 |
9 | );
10 | };
11 |
12 | export default MyComponent;
13 |
--------------------------------------------------------------------------------
/4_CSS_REACT/css/src/main.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom/client'
3 | import App from './App'
4 | import './index.css'
5 |
6 | ReactDOM.createRoot(document.getElementById('root')).render(
7 |
8 |
9 |
10 | )
11 |
--------------------------------------------------------------------------------
/5_FORM_REACT/form/src/main.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom/client'
3 | import App from './App'
4 | import './index.css'
5 |
6 | ReactDOM.createRoot(document.getElementById('root')).render(
7 |
8 |
9 |
10 | )
11 |
--------------------------------------------------------------------------------
/6_HTTP_REACT/http/src/main.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom/client'
3 | import App from './App'
4 | import './index.css'
5 |
6 | ReactDOM.createRoot(document.getElementById('root')).render(
7 |
8 |
9 |
10 | )
11 |
--------------------------------------------------------------------------------
/7_ROUTER/router/src/routes/Info.jsx:
--------------------------------------------------------------------------------
1 | import { useParams } from "react-router-dom";
2 |
3 | const Info = () => {
4 | const { id } = useParams();
5 |
6 | return (
7 |
8 |
Mais informações sobre o produto: {id}
9 |
10 | );
11 | };
12 |
13 | export default Info;
14 |
--------------------------------------------------------------------------------
/2_FUNDAMENTOS/fundamentos_react/src/main.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom/client'
3 | import App from './App'
4 | import './index.css'
5 |
6 | ReactDOM.createRoot(document.getElementById('root')).render(
7 |
8 |
9 |
10 | )
11 |
--------------------------------------------------------------------------------
/3_AVANCANDO_EM_REACT/avancando/src/main.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom/client'
3 | import App from './App'
4 | import './index.css'
5 |
6 | ReactDOM.createRoot(document.getElementById('root')).render(
7 |
8 |
9 |
10 | )
11 |
--------------------------------------------------------------------------------
/8_CONTEXT_API/context/src/components/Navbar.jsx:
--------------------------------------------------------------------------------
1 | import { NavLink } from "react-router-dom";
2 |
3 | const Navbar = () => {
4 | return (
5 |
6 | Home
7 | Contatos
8 |
9 | );
10 | };
11 |
12 | export default Navbar;
13 |
--------------------------------------------------------------------------------
/5_FORM_REACT/form/src/App.jsx:
--------------------------------------------------------------------------------
1 | import "./App.css";
2 | import MyForm from "./components/MyForm";
3 |
4 | function App() {
5 | return (
6 |
7 |
Form em React
8 |
9 |
10 | );
11 | }
12 |
13 | export default App;
14 |
--------------------------------------------------------------------------------
/1_INTRO/intro/src/App.jsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import reactLogo from "./assets/react.svg";
3 | import "./App.css";
4 |
5 | function App() {
6 | const [count, setCount] = useState(0);
7 |
8 | return (
9 |
10 |
Hello World!
11 |
12 | );
13 | }
14 |
15 | export default App;
16 |
--------------------------------------------------------------------------------
/2_FUNDAMENTOS/fundamentos_react/src/components/FirstComponent.jsx:
--------------------------------------------------------------------------------
1 | import MyComponent from "./MyComponent";
2 |
3 | // 1 - criando componente
4 | const FirstComponent = () => {
5 | return (
6 |
7 |
Meu primeiro componente!
8 |
9 |
10 | );
11 | };
12 |
13 | export default FirstComponent;
14 |
--------------------------------------------------------------------------------
/3_AVANCANDO_EM_REACT/avancando/src/components/Fragment.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | const Fragment = () => {
4 | return (
5 | <>
6 |
7 |
Temos dois elementos pai
8 |
9 |
10 |
Este também é
11 |
12 | >
13 | );
14 | };
15 |
16 | export default Fragment;
17 |
--------------------------------------------------------------------------------
/1_INTRO/intro/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/9_HOOKS/hooks/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/4_CSS_REACT/css/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/5_FORM_REACT/form/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/6_HTTP_REACT/http/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/7_ROUTER/router/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/8_CONTEXT_API/context/src/hooks/useTitleColorContext.jsx:
--------------------------------------------------------------------------------
1 | import { useContext } from "react";
2 | import { TitleColorContext } from "../context/TitleColorContext";
3 |
4 | export const useTitleColorContext = () => {
5 | const context = useContext(TitleColorContext);
6 |
7 | if (!context) {
8 | console.log("Context não encontrado!");
9 | }
10 |
11 | return context;
12 | };
13 |
--------------------------------------------------------------------------------
/8_CONTEXT_API/context/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/8_CONTEXT_API/context/src/App.jsx:
--------------------------------------------------------------------------------
1 | import "./App.css";
2 | import Navbar from "./components/Navbar";
3 |
4 | import { Outlet } from "react-router-dom";
5 |
6 | // 3 - estrutura mínima
7 | function App() {
8 | return (
9 |
10 |
11 |
Context API
12 |
13 |
14 | );
15 | }
16 |
17 | export default App;
18 |
--------------------------------------------------------------------------------
/9_HOOKS/hooks/src/components/HookUseContext.jsx:
--------------------------------------------------------------------------------
1 | import { createContext } from "react";
2 |
3 | export const SomeContext = createContext();
4 |
5 | export const HookUseContext = ({ children }) => {
6 | const contextValue = "testing context";
7 |
8 | return (
9 |
10 | {children}
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/2_FUNDAMENTOS/fundamentos_react/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/3_AVANCANDO_EM_REACT/avancando/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/8_CONTEXT_API/context/src/hooks/useCounterContext.jsx:
--------------------------------------------------------------------------------
1 | import { useContext } from "react";
2 | import { CounterContext } from "../context/CounterContext";
3 |
4 | export const useCounterContext = () => {
5 | const context = useContext(CounterContext);
6 |
7 | if (!context) {
8 | console.log("Contexto não encontado!");
9 | }
10 |
11 | console.log(context);
12 |
13 | return context;
14 | };
15 |
--------------------------------------------------------------------------------
/3_AVANCANDO_EM_REACT/avancando/src/components/CarDetails.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | const CarDetails = ({ brand, km, color }) => {
4 | return (
5 |
6 |
Detalhes do carro:
7 |
8 | - Marca: {brand}
9 | - Kilometragem: {km}
10 | - Cor: {color}
11 |
12 |
13 | );
14 | };
15 |
16 | export default CarDetails;
17 |
--------------------------------------------------------------------------------
/9_HOOKS/hooks/src/routes/Contact.jsx:
--------------------------------------------------------------------------------
1 | // useContext
2 | import { useContext } from "react";
3 | import { SomeContext } from "../components/HookUseContext";
4 |
5 | const Contact = () => {
6 | const { contextValue } = useContext(SomeContext);
7 |
8 | return (
9 |
10 |
Contato
11 |
Valor do contexto: {contextValue}
12 |
13 | );
14 | };
15 |
16 | export default Contact;
17 |
--------------------------------------------------------------------------------
/7_ROUTER/router/src/routes/ErrorPage.jsx:
--------------------------------------------------------------------------------
1 | import { useRouteError } from "react-router-dom";
2 |
3 | export default function ErrorPage() {
4 | const error = useRouteError();
5 | console.error(error);
6 |
7 | return (
8 |
9 |
Oops!
10 |
Temos um problema.
11 |
12 | {error.statusText || error.message}
13 |
14 |
15 | );
16 | }
17 |
--------------------------------------------------------------------------------
/1_INTRO/intro/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/4_CSS_REACT/css/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/7_ROUTER/router/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/9_HOOKS/hooks/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/5_FORM_REACT/form/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/6_HTTP_REACT/http/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/8_CONTEXT_API/context/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/3_AVANCANDO_EM_REACT/avancando/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/2_FUNDAMENTOS/fundamentos_react/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/9_HOOKS/hooks/src/components/List.jsx:
--------------------------------------------------------------------------------
1 | import { useState, useEffect } from "react";
2 |
3 | const List = ({ getItems }) => {
4 | const [myItems, setMyItems] = useState([]);
5 |
6 | useEffect(() => {
7 | console.log("Buscando itens do DB...");
8 |
9 | setMyItems(getItems);
10 | }, [getItems]);
11 |
12 | return (
13 | {myItems && myItems.map((item) =>
{item}
)}
14 | );
15 | };
16 |
17 | export default List;
18 |
--------------------------------------------------------------------------------
/8_CONTEXT_API/context/src/context/CounterContext.jsx:
--------------------------------------------------------------------------------
1 | // 1 - criar context
2 | import { createContext, useState } from "react";
3 |
4 | export const CounterContext = createContext();
5 |
6 | // 2 - criar provider
7 | export const CounterContextProvider = ({ children }) => {
8 | const [counter, setCounter] = useState(5);
9 |
10 | return (
11 |
12 | {children}
13 |
14 | );
15 | };
16 |
--------------------------------------------------------------------------------
/3_AVANCANDO_EM_REACT/avancando/src/components/ChangeMessageState.jsx:
--------------------------------------------------------------------------------
1 | const ChangeMessageState = ({ handleMessage }) => {
2 | const messages = ["Oi", "Olá", "Tudo bem?"];
3 |
4 | return (
5 |
6 |
7 |
8 |
9 |
10 | );
11 | };
12 |
13 | export default ChangeMessageState;
14 |
--------------------------------------------------------------------------------
/1_INTRO/intro/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "intro",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "preview": "vite preview"
10 | },
11 | "dependencies": {
12 | "react": "^18.2.0",
13 | "react-dom": "^18.2.0"
14 | },
15 | "devDependencies": {
16 | "@types/react": "^18.0.24",
17 | "@types/react-dom": "^18.0.8",
18 | "@vitejs/plugin-react": "^2.2.0",
19 | "vite": "^3.2.3"
20 | }
21 | }
--------------------------------------------------------------------------------
/4_CSS_REACT/css/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "css",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "preview": "vite preview"
10 | },
11 | "dependencies": {
12 | "react": "^18.2.0",
13 | "react-dom": "^18.2.0"
14 | },
15 | "devDependencies": {
16 | "@types/react": "^18.0.24",
17 | "@types/react-dom": "^18.0.8",
18 | "@vitejs/plugin-react": "^2.2.0",
19 | "vite": "^3.2.3"
20 | }
21 | }
--------------------------------------------------------------------------------
/5_FORM_REACT/form/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "form",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "preview": "vite preview"
10 | },
11 | "dependencies": {
12 | "react": "^18.2.0",
13 | "react-dom": "^18.2.0"
14 | },
15 | "devDependencies": {
16 | "@types/react": "^18.0.24",
17 | "@types/react-dom": "^18.0.8",
18 | "@vitejs/plugin-react": "^2.2.0",
19 | "vite": "^3.2.3"
20 | }
21 | }
--------------------------------------------------------------------------------
/2_FUNDAMENTOS/fundamentos_react/src/components/TemplateExpression.jsx:
--------------------------------------------------------------------------------
1 | // 4 - template expression
2 |
3 | const TemplateExpression = () => {
4 | const name = "Matheus";
5 |
6 | const data = {
7 | age: 31,
8 | job: "Programador",
9 | };
10 |
11 | return (
12 |
13 |
A soma é {2 + 2}
14 |
Bem-vindo {name}
15 |
16 | Sua idade é {data.age} e você trabalha como {data.job}
17 |
18 |
19 | );
20 | };
21 |
22 | export default TemplateExpression;
23 |
--------------------------------------------------------------------------------
/9_HOOKS/hooks/src/components/HookUseImperativeHandle.jsx:
--------------------------------------------------------------------------------
1 | import { useRef } from "react";
2 |
3 | import SomeComponent from "./SomeComponent";
4 |
5 | const HookUseImperativeHandle = () => {
6 | const componentRef = useRef();
7 |
8 | return (
9 |
10 |
useImperativeHandle
11 |
12 |
13 |
14 |
15 | );
16 | };
17 |
18 | export default HookUseImperativeHandle;
19 |
--------------------------------------------------------------------------------
/3_AVANCANDO_EM_REACT/avancando/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "avancando",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "preview": "vite preview"
10 | },
11 | "dependencies": {
12 | "react": "^18.2.0",
13 | "react-dom": "^18.2.0"
14 | },
15 | "devDependencies": {
16 | "@types/react": "^18.0.24",
17 | "@types/react-dom": "^18.0.8",
18 | "@vitejs/plugin-react": "^2.2.0",
19 | "vite": "^3.2.3"
20 | }
21 | }
--------------------------------------------------------------------------------
/2_FUNDAMENTOS/fundamentos_react/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "fundamentos_react",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "preview": "vite preview"
10 | },
11 | "dependencies": {
12 | "react": "^18.2.0",
13 | "react-dom": "^18.2.0"
14 | },
15 | "devDependencies": {
16 | "@types/react": "^18.0.24",
17 | "@types/react-dom": "^18.0.8",
18 | "@vitejs/plugin-react": "^2.2.0",
19 | "vite": "^3.2.3"
20 | }
21 | }
--------------------------------------------------------------------------------
/9_HOOKS/hooks/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hooks",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "preview": "vite preview"
10 | },
11 | "dependencies": {
12 | "react": "^18.2.0",
13 | "react-dom": "^18.2.0",
14 | "react-router-dom": "^6.4.5"
15 | },
16 | "devDependencies": {
17 | "@types/react": "^18.0.26",
18 | "@types/react-dom": "^18.0.9",
19 | "@vitejs/plugin-react": "^3.0.0",
20 | "vite": "^4.0.0"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/8_CONTEXT_API/context/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "context",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "preview": "vite preview"
10 | },
11 | "dependencies": {
12 | "react": "^18.2.0",
13 | "react-dom": "^18.2.0",
14 | "react-router-dom": "^6.4.5"
15 | },
16 | "devDependencies": {
17 | "@types/react": "^18.0.26",
18 | "@types/react-dom": "^18.0.9",
19 | "@vitejs/plugin-react": "^3.0.0",
20 | "vite": "^4.0.0"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/9_HOOKS/hooks/src/components/HookCustom.jsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import { usePrevious } from "../hooks/usePrevious";
3 |
4 | const HookCustom = () => {
5 | const [number, setNumber] = useState(0);
6 | const previousValue = usePrevious(number);
7 |
8 | return (
9 |
10 |
Custom Hook
11 |
Atual: {number}
12 |
Anterior: {previousValue}
13 |
14 |
15 |
16 | );
17 | };
18 |
19 | export default HookCustom;
20 |
--------------------------------------------------------------------------------
/7_ROUTER/router/src/App.jsx:
--------------------------------------------------------------------------------
1 | import "./App.css";
2 |
3 | import { Outlet } from "react-router-dom";
4 |
5 | // 6 - link entre páginas
6 | import Navbar from "./components/Navbar";
7 |
8 | // 14 - search params
9 | import SearchForm from "./components/Search";
10 |
11 | function App() {
12 | return (
13 |
14 | {/* 6 - link entre páginas */}
15 |
16 | {/* 14 - search params */}
17 |
18 |
React Router
19 |
20 |
21 | );
22 | }
23 |
24 | export default App;
25 |
--------------------------------------------------------------------------------
/8_CONTEXT_API/context/src/routes/Contact.jsx:
--------------------------------------------------------------------------------
1 | import { useContext } from "react";
2 | import { CounterContext } from "../context/CounterContext";
3 |
4 | // 5 - contexto mais complexo
5 | import { useTitleColorContext } from "../hooks/useTitleColorContext";
6 |
7 | const Contact = () => {
8 | const { counter } = useContext(CounterContext);
9 |
10 | const { color, dispatch } = useTitleColorContext();
11 |
12 | return (
13 |
14 |
Contato
15 |
Valor do contador: {counter}
16 |
17 | );
18 | };
19 |
20 | export default Contact;
21 |
--------------------------------------------------------------------------------
/3_AVANCANDO_EM_REACT/avancando/src/components/Data.jsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 |
3 | const Data = () => {
4 | let someData = 10;
5 |
6 | const [anotherNumber, setAnotherNumber] = useState(15);
7 |
8 | return (
9 |
10 |
11 |
Valor: {someData}
12 |
13 |
14 |
15 |
Valor: {anotherNumber}
16 |
17 |
18 |
19 | );
20 | };
21 |
22 | export default Data;
23 |
--------------------------------------------------------------------------------
/9_HOOKS/hooks/src/App.jsx:
--------------------------------------------------------------------------------
1 | import { Link, Outlet } from "react-router-dom";
2 | import { useContext } from "react";
3 | import { SomeContext } from "./components/HookUseContext";
4 | import "./App.css";
5 |
6 | function App() {
7 | const { contextValue } = useContext(SomeContext);
8 |
9 | return (
10 |
11 |
12 | -
13 | Home
14 |
15 | -
16 | Contato
17 |
18 |
19 |
20 |
21 | );
22 | }
23 |
24 | export default App;
25 |
--------------------------------------------------------------------------------
/6_HTTP_REACT/http/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "http",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "preview": "vite preview",
10 | "server": "json-server --watch data/db.json"
11 | },
12 | "dependencies": {
13 | "json-server": "^0.17.1",
14 | "react": "^18.2.0",
15 | "react-dom": "^18.2.0"
16 | },
17 | "devDependencies": {
18 | "@types/react": "^18.0.24",
19 | "@types/react-dom": "^18.0.8",
20 | "@vitejs/plugin-react": "^2.2.0",
21 | "vite": "^3.2.3"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/7_ROUTER/router/src/components/Search.jsx:
--------------------------------------------------------------------------------
1 | import { useNavigate } from "react-router-dom";
2 |
3 | import { useState } from "react";
4 |
5 | const SearchForm = () => {
6 | const navigate = useNavigate();
7 | const [query, setQuery] = useState();
8 |
9 | const handleSubmit = (e) => {
10 | e.preventDefault();
11 |
12 | navigate("/search?q=" + query);
13 | };
14 |
15 | return (
16 |
20 | );
21 | };
22 |
23 | export default SearchForm;
24 |
--------------------------------------------------------------------------------
/9_HOOKS/hooks/src/components/HookUseCallback.jsx:
--------------------------------------------------------------------------------
1 | import { useCallback, useState } from "react";
2 |
3 | import List from "./List";
4 |
5 | const HookUseCallback = () => {
6 | const [counter, setCounter] = useState(0);
7 |
8 | const getItemsFromDatabase = useCallback(() => {
9 | return ["a", "b", "c"];
10 | }, []);
11 |
12 | return (
13 |
14 |
useCallback
15 |
16 |
17 |
{counter}
18 |
19 |
20 | );
21 | };
22 |
23 | export default HookUseCallback;
24 |
--------------------------------------------------------------------------------
/7_ROUTER/router/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "router",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "preview": "vite preview",
10 | "server": "json-server --watch data/db.json"
11 | },
12 | "dependencies": {
13 | "json-server": "^0.17.1",
14 | "react": "^18.2.0",
15 | "react-dom": "^18.2.0",
16 | "react-router-dom": "^6.4.4"
17 | },
18 | "devDependencies": {
19 | "@types/react": "^18.0.24",
20 | "@types/react-dom": "^18.0.8",
21 | "@vitejs/plugin-react": "^2.2.0",
22 | "vite": "^3.2.3"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/9_HOOKS/hooks/src/components/HookUseLayoutEffect.jsx:
--------------------------------------------------------------------------------
1 | import { useLayoutEffect, useEffect, useState } from "react";
2 |
3 | const HookUseLayoutEffect = () => {
4 | const [name, setName] = useState("Algum nome");
5 |
6 | useEffect(() => {
7 | console.log("2");
8 | setName("Mudou de novo!");
9 | }, []);
10 |
11 | useLayoutEffect(() => {
12 | console.log("1");
13 | setName("Outro nome");
14 | }, []);
15 |
16 | console.log(name);
17 |
18 | return (
19 |
20 |
useLayoutEffect
21 |
Nome: {name}
22 |
23 |
24 | );
25 | };
26 |
27 | export default HookUseLayoutEffect;
28 |
--------------------------------------------------------------------------------
/8_CONTEXT_API/context/src/components/ChangeCounter.jsx:
--------------------------------------------------------------------------------
1 | // 3 - alterando valor do contexto
2 | import { useContext } from "react";
3 |
4 | import { CounterContext } from "../context/CounterContext";
5 |
6 | // 4 - refatorando com hook
7 | import { useCounterContext } from "../hooks/useCounterContext";
8 |
9 | const ChangeCounter = () => {
10 | // const { counter, setCounter } = useContext(CounterContext);
11 | const { counter, setCounter } = useCounterContext();
12 |
13 | return (
14 |
15 |
16 |
17 | );
18 | };
19 |
20 | export default ChangeCounter;
21 |
--------------------------------------------------------------------------------
/9_HOOKS/hooks/src/components/SomeComponent.jsx:
--------------------------------------------------------------------------------
1 | import { forwardRef, useRef, useImperativeHandle } from "react";
2 |
3 | const SomeComponent = forwardRef((props, ref) => {
4 | const localInputRef = useRef();
5 |
6 | useImperativeHandle(ref, () => {
7 | return {
8 | validate: () => {
9 | if (localInputRef.current.value.length > 3) {
10 | localInputRef.current.value = "";
11 | }
12 | },
13 | };
14 | });
15 |
16 | return (
17 |
18 |
Insira no máximo 3 caracteres
19 |
20 |
21 | );
22 | });
23 |
24 | export default SomeComponent;
25 |
--------------------------------------------------------------------------------
/3_AVANCANDO_EM_REACT/avancando/src/components/ConditionalRender.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | const ConditionalRender = () => {
4 | const x = true;
5 |
6 | const name = "Matheus";
7 |
8 | return (
9 |
10 | {/* 7 - render condicional */}
11 |
Isso será exibido?
12 | {x &&
Se x for true sim!
}
13 | {/* 8 - adicionando else */}
14 |
Render ternário:
15 | {name === "João" ? (
16 |
19 | ) : (
20 |
21 |
Nome não encontrado!
22 |
23 | )}
24 |
25 | );
26 | };
27 |
28 | export default ConditionalRender;
29 |
--------------------------------------------------------------------------------
/7_ROUTER/router/src/components/Navbar.jsx:
--------------------------------------------------------------------------------
1 | import { Link } from "react-router-dom";
2 |
3 | // 12 - link ativo
4 | import { NavLink } from "react-router-dom";
5 |
6 | import "./Navbar.css";
7 |
8 | const Navbar = () => {
9 | return (
10 |
11 | {/* Home
12 | Contatos */}
13 | {/* */}
14 | (isActive ? "active" : "")}>
15 | Home
16 |
17 | (isActive ? "active" : "")}
20 | >
21 | Contatos
22 |
23 |
24 | );
25 | };
26 |
27 | export default Navbar;
28 |
--------------------------------------------------------------------------------
/9_HOOKS/hooks/src/components/HookUseMemo.jsx:
--------------------------------------------------------------------------------
1 | import { useState, useEffect, useMemo } from "react";
2 |
3 | const HookUseMemo = () => {
4 | const [number, setNumber] = useState(0);
5 |
6 | // const premiumNumbers = ["0", "100", "200"];
7 |
8 | const premiumNumbers = useMemo(() => {
9 | return ["0", "100", "200"];
10 | }, []);
11 |
12 | useEffect(() => {
13 | console.log("Premium numbers foi alterado!");
14 | }, [premiumNumbers]);
15 |
16 | return (
17 |
18 |
useMemo
19 |
setNumber(e.target.value)} />
20 | {premiumNumbers.includes(number) ?
Acertou o número
: ""}
21 |
22 |
23 | );
24 | };
25 |
26 | export default HookUseMemo;
27 |
--------------------------------------------------------------------------------
/7_ROUTER/router/data/db.json:
--------------------------------------------------------------------------------
1 | {
2 | "products": [
3 | {
4 | "name": "capa de chuva",
5 | "price": "50.50",
6 | "id": 5
7 | },
8 | {
9 | "name": "teclado",
10 | "price": "110",
11 | "id": 6
12 | },
13 | {
14 | "name": "cadeira",
15 | "price": "200",
16 | "id": 7
17 | },
18 | {
19 | "name": "mouse",
20 | "price": "60",
21 | "id": 8
22 | },
23 | {
24 | "name": "suporte monitor",
25 | "price": "120",
26 | "id": 9
27 | },
28 | {
29 | "name": "cabo hdmi",
30 | "price": "10",
31 | "id": 11
32 | },
33 | {
34 | "name": "suporte microfone",
35 | "price": "60",
36 | "id": 12
37 | }
38 | ]
39 | }
40 |
--------------------------------------------------------------------------------
/1_INTRO/intro/src/App.css:
--------------------------------------------------------------------------------
1 | #root {
2 | max-width: 1280px;
3 | margin: 0 auto;
4 | padding: 2rem;
5 | text-align: center;
6 | }
7 |
8 | .logo {
9 | height: 6em;
10 | padding: 1.5em;
11 | will-change: filter;
12 | }
13 | .logo:hover {
14 | filter: drop-shadow(0 0 2em #646cffaa);
15 | }
16 | .logo.react:hover {
17 | filter: drop-shadow(0 0 2em #61dafbaa);
18 | }
19 |
20 | @keyframes logo-spin {
21 | from {
22 | transform: rotate(0deg);
23 | }
24 | to {
25 | transform: rotate(360deg);
26 | }
27 | }
28 |
29 | @media (prefers-reduced-motion: no-preference) {
30 | a:nth-of-type(2) .logo {
31 | animation: logo-spin infinite 20s linear;
32 | }
33 | }
34 |
35 | .card {
36 | padding: 2em;
37 | }
38 |
39 | .read-the-docs {
40 | color: #888;
41 | }
42 |
--------------------------------------------------------------------------------
/4_CSS_REACT/css/src/App.css:
--------------------------------------------------------------------------------
1 | #root {
2 | max-width: 1280px;
3 | margin: 0 auto;
4 | padding: 2rem;
5 | text-align: center;
6 | }
7 |
8 | .logo {
9 | height: 6em;
10 | padding: 1.5em;
11 | will-change: filter;
12 | }
13 | .logo:hover {
14 | filter: drop-shadow(0 0 2em #646cffaa);
15 | }
16 | .logo.react:hover {
17 | filter: drop-shadow(0 0 2em #61dafbaa);
18 | }
19 |
20 | @keyframes logo-spin {
21 | from {
22 | transform: rotate(0deg);
23 | }
24 | to {
25 | transform: rotate(360deg);
26 | }
27 | }
28 |
29 | @media (prefers-reduced-motion: no-preference) {
30 | a:nth-of-type(2) .logo {
31 | animation: logo-spin infinite 20s linear;
32 | }
33 | }
34 |
35 | .card {
36 | padding: 2em;
37 | }
38 |
39 | .read-the-docs {
40 | color: #888;
41 | }
42 |
--------------------------------------------------------------------------------
/5_FORM_REACT/form/src/App.css:
--------------------------------------------------------------------------------
1 | #root {
2 | max-width: 1280px;
3 | margin: 0 auto;
4 | padding: 2rem;
5 | text-align: center;
6 | }
7 |
8 | .logo {
9 | height: 6em;
10 | padding: 1.5em;
11 | will-change: filter;
12 | }
13 | .logo:hover {
14 | filter: drop-shadow(0 0 2em #646cffaa);
15 | }
16 | .logo.react:hover {
17 | filter: drop-shadow(0 0 2em #61dafbaa);
18 | }
19 |
20 | @keyframes logo-spin {
21 | from {
22 | transform: rotate(0deg);
23 | }
24 | to {
25 | transform: rotate(360deg);
26 | }
27 | }
28 |
29 | @media (prefers-reduced-motion: no-preference) {
30 | a:nth-of-type(2) .logo {
31 | animation: logo-spin infinite 20s linear;
32 | }
33 | }
34 |
35 | .card {
36 | padding: 2em;
37 | }
38 |
39 | .read-the-docs {
40 | color: #888;
41 | }
42 |
--------------------------------------------------------------------------------
/7_ROUTER/router/src/App.css:
--------------------------------------------------------------------------------
1 | #root {
2 | max-width: 1280px;
3 | margin: 0 auto;
4 | padding: 2rem;
5 | text-align: center;
6 | }
7 |
8 | .logo {
9 | height: 6em;
10 | padding: 1.5em;
11 | will-change: filter;
12 | }
13 | .logo:hover {
14 | filter: drop-shadow(0 0 2em #646cffaa);
15 | }
16 | .logo.react:hover {
17 | filter: drop-shadow(0 0 2em #61dafbaa);
18 | }
19 |
20 | @keyframes logo-spin {
21 | from {
22 | transform: rotate(0deg);
23 | }
24 | to {
25 | transform: rotate(360deg);
26 | }
27 | }
28 |
29 | @media (prefers-reduced-motion: no-preference) {
30 | a:nth-of-type(2) .logo {
31 | animation: logo-spin infinite 20s linear;
32 | }
33 | }
34 |
35 | .card {
36 | padding: 2em;
37 | }
38 |
39 | .read-the-docs {
40 | color: #888;
41 | }
42 |
--------------------------------------------------------------------------------
/9_HOOKS/hooks/src/App.css:
--------------------------------------------------------------------------------
1 | #root {
2 | max-width: 1280px;
3 | margin: 0 auto;
4 | padding: 2rem;
5 | text-align: center;
6 | }
7 |
8 | .logo {
9 | height: 6em;
10 | padding: 1.5em;
11 | will-change: filter;
12 | }
13 | .logo:hover {
14 | filter: drop-shadow(0 0 2em #646cffaa);
15 | }
16 | .logo.react:hover {
17 | filter: drop-shadow(0 0 2em #61dafbaa);
18 | }
19 |
20 | @keyframes logo-spin {
21 | from {
22 | transform: rotate(0deg);
23 | }
24 | to {
25 | transform: rotate(360deg);
26 | }
27 | }
28 |
29 | @media (prefers-reduced-motion: no-preference) {
30 | a:nth-of-type(2) .logo {
31 | animation: logo-spin infinite 20s linear;
32 | }
33 | }
34 |
35 | .card {
36 | padding: 2em;
37 | }
38 |
39 | .read-the-docs {
40 | color: #888;
41 | }
42 |
--------------------------------------------------------------------------------
/8_CONTEXT_API/context/src/App.css:
--------------------------------------------------------------------------------
1 | #root {
2 | max-width: 1280px;
3 | margin: 0 auto;
4 | padding: 2rem;
5 | text-align: center;
6 | }
7 |
8 | .logo {
9 | height: 6em;
10 | padding: 1.5em;
11 | will-change: filter;
12 | }
13 | .logo:hover {
14 | filter: drop-shadow(0 0 2em #646cffaa);
15 | }
16 | .logo.react:hover {
17 | filter: drop-shadow(0 0 2em #61dafbaa);
18 | }
19 |
20 | @keyframes logo-spin {
21 | from {
22 | transform: rotate(0deg);
23 | }
24 | to {
25 | transform: rotate(360deg);
26 | }
27 | }
28 |
29 | @media (prefers-reduced-motion: no-preference) {
30 | a:nth-of-type(2) .logo {
31 | animation: logo-spin infinite 20s linear;
32 | }
33 | }
34 |
35 | .card {
36 | padding: 2em;
37 | }
38 |
39 | .read-the-docs {
40 | color: #888;
41 | }
42 |
--------------------------------------------------------------------------------
/2_FUNDAMENTOS/fundamentos_react/src/App.css:
--------------------------------------------------------------------------------
1 | #root {
2 | max-width: 1280px;
3 | margin: 0 auto;
4 | padding: 2rem;
5 | text-align: center;
6 | }
7 |
8 | .logo {
9 | height: 6em;
10 | padding: 1.5em;
11 | will-change: filter;
12 | }
13 | .logo:hover {
14 | filter: drop-shadow(0 0 2em #646cffaa);
15 | }
16 | .logo.react:hover {
17 | filter: drop-shadow(0 0 2em #61dafbaa);
18 | }
19 |
20 | @keyframes logo-spin {
21 | from {
22 | transform: rotate(0deg);
23 | }
24 | to {
25 | transform: rotate(360deg);
26 | }
27 | }
28 |
29 | @media (prefers-reduced-motion: no-preference) {
30 | a:nth-of-type(2) .logo {
31 | animation: logo-spin infinite 20s linear;
32 | }
33 | }
34 |
35 | .card {
36 | padding: 2em;
37 | }
38 |
39 | .read-the-docs {
40 | color: #888;
41 | }
42 |
--------------------------------------------------------------------------------
/3_AVANCANDO_EM_REACT/avancando/src/App.css:
--------------------------------------------------------------------------------
1 | #root {
2 | max-width: 1280px;
3 | margin: 0 auto;
4 | padding: 2rem;
5 | text-align: center;
6 | }
7 |
8 | .logo {
9 | height: 6em;
10 | padding: 1.5em;
11 | will-change: filter;
12 | }
13 | .logo:hover {
14 | filter: drop-shadow(0 0 2em #646cffaa);
15 | }
16 | .logo.react:hover {
17 | filter: drop-shadow(0 0 2em #61dafbaa);
18 | }
19 |
20 | @keyframes logo-spin {
21 | from {
22 | transform: rotate(0deg);
23 | }
24 | to {
25 | transform: rotate(360deg);
26 | }
27 | }
28 |
29 | @media (prefers-reduced-motion: no-preference) {
30 | a:nth-of-type(2) .logo {
31 | animation: logo-spin infinite 20s linear;
32 | }
33 | }
34 |
35 | .card {
36 | padding: 2em;
37 | }
38 |
39 | .read-the-docs {
40 | color: #888;
41 | }
42 |
--------------------------------------------------------------------------------
/2_FUNDAMENTOS/fundamentos_react/src/App.jsx:
--------------------------------------------------------------------------------
1 | // 2 - importando componente
2 | import FirstComponent from "./components/FirstComponent";
3 |
4 | // 4 - template expression
5 | import TemplateExpression from "./components/TemplateExpression";
6 |
7 | // 5 - hierarquia de componentes
8 | import MyComponent from "./components/MyComponent";
9 |
10 | // 6 - eventos
11 | import Events from "./components/Events";
12 |
13 | import "./App.css";
14 |
15 | function App() {
16 | // 3 - Comentários na função ou fora
17 | return (
18 |
19 | {/* 3 - Comentários no componente */}
20 |
Fundamentos do React
21 |
22 |
23 |
24 |
25 |
26 | );
27 | }
28 |
29 | export default App;
30 |
--------------------------------------------------------------------------------
/8_CONTEXT_API/context/src/context/TitleColorContext.jsx:
--------------------------------------------------------------------------------
1 | import { createContext, useReducer } from "react";
2 |
3 | export const TitleColorContext = createContext();
4 |
5 | export const titleColorReducer = (state, action) => {
6 | switch (action.type) {
7 | case "RED":
8 | return { ...state, color: "red" };
9 | case "BLUE":
10 | return { ...state, color: "blue" };
11 | default:
12 | return state;
13 | }
14 | };
15 |
16 | export const TitleColorContextProvider = ({ children }) => {
17 | const [state, dispatch] = useReducer(titleColorReducer, { color: "purple" });
18 |
19 | console.log("Title color context: ", state);
20 |
21 | return (
22 |
23 | {children}
24 |
25 | );
26 | };
27 |
--------------------------------------------------------------------------------
/7_ROUTER/router/src/routes/Search.jsx:
--------------------------------------------------------------------------------
1 | import { useSearchParams, Link } from "react-router-dom";
2 | import { useFetch } from "../hooks/useFetch";
3 |
4 | const Search = () => {
5 | const [searchParams] = useSearchParams();
6 |
7 | const url = "http://localhost:3000/products?" + searchParams;
8 |
9 | const { data: items, loading, error } = useFetch(url);
10 |
11 | return (
12 |
13 |
Resultados disponíveis
14 |
15 | {items &&
16 | items.map((item) => (
17 | -
18 |
{item.name}
19 | R$: {item.price}
20 | Detalhes
21 |
22 | ))}
23 |
24 |
25 | );
26 | };
27 |
28 | export default Search;
29 |
--------------------------------------------------------------------------------
/7_ROUTER/router/src/routes/Product.jsx:
--------------------------------------------------------------------------------
1 | import { Link, useParams } from "react-router-dom";
2 | import { useFetch } from "../hooks/useFetch";
3 |
4 | const Product = () => {
5 | const { id } = useParams();
6 |
7 | const url = "http://localhost:3000/products/" + id;
8 |
9 | const { data: product, loading, error } = useFetch(url);
10 |
11 | console.log(product);
12 |
13 | return (
14 | <>
15 | ID do produto: {id}
16 | {error && Ocorreu um erro...
}
17 | {loading && Carregando...
}
18 | {product && (
19 |
20 |
{product.name}
21 |
R${product.price}
22 | {/* 11 - nested routes */}
23 |
Mais informações
24 |
25 | )}
26 | >
27 | );
28 | };
29 |
30 | export default Product;
31 |
--------------------------------------------------------------------------------
/7_ROUTER/router/src/routes/Home.jsx:
--------------------------------------------------------------------------------
1 | // 7 - carregamento de dados
2 | import { useFetch } from "../hooks/useFetch";
3 |
4 | const url = "http://localhost:3000/products";
5 |
6 | // 8 - carregamento individual - rota dinâmica
7 | import { Link } from "react-router-dom";
8 |
9 | const Home = () => {
10 | const { data: items, loading, error } = useFetch(url);
11 |
12 | return (
13 |
14 |
Home
15 | {/* 7 - Carregamento de dados */}
16 |
17 | {items &&
18 | items.map((item) => (
19 | -
20 |
{item.name}
21 | R$: {item.price}
22 | {/* 8 - rota dinamica */}
23 | Detalhes
24 |
25 | ))}
26 |
27 |
28 | );
29 | };
30 |
31 | export default Home;
32 |
--------------------------------------------------------------------------------
/9_HOOKS/hooks/src/main.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom/client";
3 | import { HookUseContext } from "./components/HookUseContext";
4 | import App from "./App";
5 | import "./index.css";
6 |
7 | import { createBrowserRouter, RouterProvider } from "react-router-dom";
8 | import Home from "./routes/Home";
9 | import Contact from "./routes/Contact";
10 |
11 | const router = createBrowserRouter([
12 | {
13 | path: "/",
14 | element: ,
15 | children: [
16 | {
17 | path: "/",
18 | element: ,
19 | },
20 | {
21 | path: "contact",
22 | element: ,
23 | },
24 | ],
25 | },
26 | ]);
27 |
28 | ReactDOM.createRoot(document.getElementById("root")).render(
29 |
30 |
31 |
32 |
33 |
34 | );
35 |
--------------------------------------------------------------------------------
/2_FUNDAMENTOS/fundamentos_react/src/components/Events.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | const Events = () => {
4 | const handleClick = (e) => {
5 | console.log(e);
6 | console.log("Ativou o evento!");
7 | };
8 |
9 | // 8 - Função de renderizacao
10 | const renderSomething = (x) => {
11 | if (x) {
12 | return Renderizando isso!
;
13 | } else {
14 | return Também posso renderizar isso!
;
15 | }
16 | };
17 |
18 | return (
19 |
20 | {/* 6 - eventos */}
21 |
22 |
25 |
26 | {/* 7 - evento com função */}
27 |
28 |
29 |
30 | {/* 8 - Função de render */}
31 | {renderSomething(true)}
32 | {renderSomething(false)}
33 |
34 | );
35 | };
36 |
37 | export default Events;
38 |
--------------------------------------------------------------------------------
/6_HTTP_REACT/http/src/App.css:
--------------------------------------------------------------------------------
1 | #root {
2 | max-width: 1280px;
3 | margin: 0 auto;
4 | padding: 2rem;
5 | text-align: center;
6 | }
7 |
8 | .logo {
9 | height: 6em;
10 | padding: 1.5em;
11 | will-change: filter;
12 | }
13 | .logo:hover {
14 | filter: drop-shadow(0 0 2em #646cffaa);
15 | }
16 | .logo.react:hover {
17 | filter: drop-shadow(0 0 2em #61dafbaa);
18 | }
19 |
20 | @keyframes logo-spin {
21 | from {
22 | transform: rotate(0deg);
23 | }
24 | to {
25 | transform: rotate(360deg);
26 | }
27 | }
28 |
29 | @media (prefers-reduced-motion: no-preference) {
30 | a:nth-of-type(2) .logo {
31 | animation: logo-spin infinite 20s linear;
32 | }
33 | }
34 |
35 | .card {
36 | padding: 2em;
37 | }
38 |
39 | .read-the-docs {
40 | color: #888;
41 | }
42 |
43 | .add-product {
44 | border-top: 1px solid #000;
45 | }
46 |
47 | form {
48 | display: flex;
49 | flex-direction: column;
50 | align-items: center;
51 | justify-content: center;
52 | }
53 |
54 | form input {
55 | display: flex;
56 | flex-direction: column;
57 | margin-bottom: 15px;
58 | }
59 |
--------------------------------------------------------------------------------
/8_CONTEXT_API/context/src/main.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom/client";
3 | import App from "./App";
4 | import "./index.css";
5 |
6 | // 2 - criando o provider
7 | import { CounterContextProvider } from "./context/CounterContext";
8 |
9 | // 3 - criando uma estrutura
10 | import { createBrowserRouter, RouterProvider } from "react-router-dom";
11 |
12 | import Contact from "./routes/Contact";
13 | import Home from "./routes/Home";
14 |
15 | // 5 - contexto mais complexo
16 | import { TitleColorContextProvider } from "./context/TitleColorContext";
17 |
18 | const router = createBrowserRouter([
19 | {
20 | path: "/",
21 | element: ,
22 | children: [
23 | {
24 | path: "/",
25 | element: ,
26 | },
27 | {
28 | path: "contact",
29 | element: ,
30 | },
31 | ],
32 | },
33 | ]);
34 |
35 | ReactDOM.createRoot(document.getElementById("root")).render(
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | );
44 |
--------------------------------------------------------------------------------
/3_AVANCANDO_EM_REACT/avancando/src/components/ListRender.jsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 |
3 | const ListRender = () => {
4 | const [list] = useState(["Matheus", "Pedro", "Josias"]);
5 |
6 | const [users, setUsers] = useState([
7 | { id: 1, name: "Matheus", age: 31 },
8 | { id: 2, name: "Jones", age: 19 },
9 | { id: 3, name: "Scorpion", age: 201 },
10 | ]);
11 |
12 | // 6 - previous state
13 | const deleteRandom = () => {
14 | const randomNumber = Math.floor(Math.random() * 4);
15 |
16 | setUsers((prevUsers) => {
17 | return prevUsers.filter((user) => randomNumber !== user.id);
18 | });
19 | };
20 |
21 | return (
22 |
23 | {/* 4 - render de lista, sem key */}
24 |
25 | {list.map((item, i) => (
26 | - {item}
27 | ))}
28 |
29 | {/* 5 - render de lista com key */}
30 |
31 | {users.map((user) => (
32 | -
33 | {user.name} - {user.age} anos
34 |
35 | ))}
36 |
37 | {/* 6 - previous state */}
38 |
39 |
40 | );
41 | };
42 |
43 | export default ListRender;
44 |
--------------------------------------------------------------------------------
/9_HOOKS/hooks/src/components/HookUseState.jsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 |
3 | const HookUseState = () => {
4 | // 1 - useState
5 | let userName = "João";
6 |
7 | const [name, setName] = useState("Matheus");
8 |
9 | const changeNames = () => {
10 | userName = "João Souza";
11 |
12 | setName("Matheus Battisti");
13 |
14 | console.log(userName);
15 | };
16 |
17 | console.log(name);
18 |
19 | // 2 - useState e input
20 | const [age, setAge] = useState(18);
21 |
22 | const handleSubmit = (e) => {
23 | e.preventDefault();
24 |
25 | // envio a uma API
26 | console.log(age);
27 | };
28 |
29 | return (
30 |
31 | {/* 1 - useState */}
32 |
useState
33 |
Variável: {userName}
34 |
useState: {name}
35 |
36 | {/* 2 - useState e input */}
37 |
Digite a sua idade:
38 |
46 |
Você tem {age} anos!
47 |
48 |
49 | );
50 | };
51 |
52 | export default HookUseState;
53 |
--------------------------------------------------------------------------------
/8_CONTEXT_API/context/src/routes/Home.jsx:
--------------------------------------------------------------------------------
1 | // 3 - alterando valor do contexto
2 | import { useContext } from "react";
3 | import ChangeCounter from "../components/ChangeCounter";
4 | // import { CounterContext } from "../context/CounterContext";
5 |
6 | // 4 - refatorando com hook
7 | import { useCounterContext } from "../hooks/useCounterContext";
8 |
9 | // 5 - contexto mais complexo
10 | import { useTitleColorContext } from "../hooks/useTitleColorContext";
11 |
12 | const Home = () => {
13 | // const { counter } = useContext(CounterContext);
14 | const { counter } = useCounterContext();
15 |
16 | // 5 - contexto mais complexo
17 | const { color, dispatch } = useTitleColorContext();
18 |
19 | // 6 - alterando contexto complexo
20 | const setTitleColor = (color) => {
21 | dispatch({ type: color });
22 | };
23 |
24 | return (
25 |
26 |
Home
27 | {/* 3 - alterando o valor do contexto */}
28 |
Valor do contador: {counter}
29 |
30 | {/* 6 - alterando contexto complexo */}
31 |
32 |
33 |
34 |
35 |
36 | );
37 | };
38 |
39 | export default Home;
40 |
--------------------------------------------------------------------------------
/9_HOOKS/hooks/src/components/HookUseRef.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState, useRef } from "react";
2 |
3 | const HookUseRef = () => {
4 | // 1 - useRef
5 | const numberRef = useRef(0);
6 | const [counter, setCounter] = useState(0);
7 | const [counterB, setCounterB] = useState(0);
8 |
9 | useEffect(() => {
10 | numberRef.current = numberRef.current + 1;
11 | });
12 |
13 | // 2 - useRef e DOM
14 | const inputRef = useRef();
15 | const [text, setText] = useState("");
16 |
17 | const handleSubmit = (e) => {
18 | e.preventDefault();
19 |
20 | setText("");
21 |
22 | inputRef.current.focus();
23 | };
24 |
25 | return (
26 |
27 |
useRef
28 | {/* 1 - useRef */}
29 |
O componente renderizou: {numberRef.current} vezes.
30 |
Counter 1: {counter}
31 |
32 |
Counter 2: {counterB}
33 |
34 | {/* 2 - useRef e DOM */}
35 |
44 |
45 |
46 | );
47 | };
48 |
49 | export default HookUseRef;
50 |
--------------------------------------------------------------------------------
/4_CSS_REACT/css/src/App.jsx:
--------------------------------------------------------------------------------
1 | // 2 - CSS de componente
2 | import MyComponent from "./components/MyComponent";
3 |
4 | // 6 - CSS Modules
5 | import Title from "./components/Title";
6 |
7 | function App() {
8 | // 4 - css inline dinamico
9 | const n = 15;
10 |
11 | // 5 - classes dinamicas
12 | const redTitle = true;
13 |
14 | return (
15 |
16 | {/* 1 - css global */}
17 |
CSS no React
18 | {/* 2 - css de componente */}
19 |
Pegou CSS do componente
20 |
21 | {/* 3 - inline css */}
22 |
29 | Este elemento foi estilizado inline
30 |
31 | {/* 4 - css inline dinamico */}
32 |
10 ? { color: "purple" } : { color: "magenta" }}>
33 | CSS dinâmico
34 |
35 |
36 | CSS dinâmico 2
37 |
38 | {/* 5 - classes dinamicas */}
39 |
40 | Este título vai ter uma classe dinâmica
41 |
42 | {/* 6 - CSS modules */}
43 |
44 |
Este não recebe título do CSS modules
45 |
46 | );
47 | }
48 |
49 | export default App;
50 |
--------------------------------------------------------------------------------
/1_INTRO/intro/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/4_CSS_REACT/css/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/7_ROUTER/router/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/9_HOOKS/hooks/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/5_FORM_REACT/form/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/6_HTTP_REACT/http/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/8_CONTEXT_API/context/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/3_AVANCANDO_EM_REACT/avancando/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/2_FUNDAMENTOS/fundamentos_react/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/9_HOOKS/hooks/src/components/HookUseEffect.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react";
2 |
3 | const HookUseEffect = () => {
4 | // 1 - useEffect, sem dependências
5 | useEffect(() => {
6 | console.log("Estou sendo executado!");
7 | });
8 |
9 | const [number, setNumber] = useState(1);
10 |
11 | const changeSomething = () => {
12 | setNumber(number + 1);
13 | };
14 |
15 | // 2 - array de deps. vazio
16 | useEffect(() => {
17 | console.log("Serei executado apenas uma vez!");
18 | }, []);
19 |
20 | // 3 - item no array de deps.
21 | const [anotherNumber, setAnotherNumber] = useState(0);
22 |
23 | useEffect(() => {
24 | if (anotherNumber > 0) {
25 | console.log("Sou executado apenas quando o anotherNumber muda!");
26 | }
27 | }, [anotherNumber]);
28 |
29 | // 4 - cleanup do useEffect
30 | useEffect(() => {
31 | // const timer = setTimeout(() => {
32 | // console.log("Hello World");
33 | // setAnotherNumber(anotherNumber + 1);
34 | // }, 2000);
35 | // return () => clearTimeout(timer);
36 | }, [anotherNumber]);
37 |
38 | return (
39 |
40 |
useEffect
41 |
Number: {number}
42 |
43 |
Another Number: {anotherNumber}
44 |
47 |
48 |
49 | );
50 | };
51 |
52 | export default HookUseEffect;
53 |
--------------------------------------------------------------------------------
/1_INTRO/intro/src/index.css:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
3 | font-size: 16px;
4 | line-height: 24px;
5 | font-weight: 400;
6 |
7 | color-scheme: light dark;
8 | color: rgba(255, 255, 255, 0.87);
9 | background-color: #242424;
10 |
11 | font-synthesis: none;
12 | text-rendering: optimizeLegibility;
13 | -webkit-font-smoothing: antialiased;
14 | -moz-osx-font-smoothing: grayscale;
15 | -webkit-text-size-adjust: 100%;
16 | }
17 |
18 | a {
19 | font-weight: 500;
20 | color: #646cff;
21 | text-decoration: inherit;
22 | }
23 | a:hover {
24 | color: #535bf2;
25 | }
26 |
27 | body {
28 | margin: 0;
29 | display: flex;
30 | place-items: center;
31 | min-width: 320px;
32 | min-height: 100vh;
33 | }
34 |
35 | h1 {
36 | font-size: 3.2em;
37 | line-height: 1.1;
38 | }
39 |
40 | button {
41 | border-radius: 8px;
42 | border: 1px solid transparent;
43 | padding: 0.6em 1.2em;
44 | font-size: 1em;
45 | font-weight: 500;
46 | font-family: inherit;
47 | background-color: #1a1a1a;
48 | cursor: pointer;
49 | transition: border-color 0.25s;
50 | }
51 | button:hover {
52 | border-color: #646cff;
53 | }
54 | button:focus,
55 | button:focus-visible {
56 | outline: 4px auto -webkit-focus-ring-color;
57 | }
58 |
59 | @media (prefers-color-scheme: light) {
60 | :root {
61 | color: #213547;
62 | background-color: #ffffff;
63 | }
64 | a:hover {
65 | color: #747bff;
66 | }
67 | button {
68 | background-color: #f9f9f9;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/9_HOOKS/hooks/src/index.css:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
3 | font-size: 16px;
4 | line-height: 24px;
5 | font-weight: 400;
6 |
7 | color-scheme: light dark;
8 | color: rgba(255, 255, 255, 0.87);
9 | background-color: #242424;
10 |
11 | font-synthesis: none;
12 | text-rendering: optimizeLegibility;
13 | -webkit-font-smoothing: antialiased;
14 | -moz-osx-font-smoothing: grayscale;
15 | -webkit-text-size-adjust: 100%;
16 | }
17 |
18 | a {
19 | font-weight: 500;
20 | color: #646cff;
21 | text-decoration: inherit;
22 | }
23 | a:hover {
24 | color: #535bf2;
25 | }
26 |
27 | body {
28 | margin: 0;
29 | display: flex;
30 | place-items: center;
31 | min-width: 320px;
32 | min-height: 100vh;
33 | }
34 |
35 | h1 {
36 | font-size: 3.2em;
37 | line-height: 1.1;
38 | }
39 |
40 | button {
41 | border-radius: 8px;
42 | border: 1px solid transparent;
43 | padding: 0.6em 1.2em;
44 | font-size: 1em;
45 | font-weight: 500;
46 | font-family: inherit;
47 | background-color: #1a1a1a;
48 | cursor: pointer;
49 | transition: border-color 0.25s;
50 | }
51 | button:hover {
52 | border-color: #646cff;
53 | }
54 | button:focus,
55 | button:focus-visible {
56 | outline: 4px auto -webkit-focus-ring-color;
57 | }
58 |
59 | @media (prefers-color-scheme: light) {
60 | :root {
61 | color: #213547;
62 | background-color: #ffffff;
63 | }
64 | a:hover {
65 | color: #747bff;
66 | }
67 | button {
68 | background-color: #f9f9f9;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/5_FORM_REACT/form/src/index.css:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
3 | font-size: 16px;
4 | line-height: 24px;
5 | font-weight: 400;
6 |
7 | color-scheme: light dark;
8 | color: rgba(255, 255, 255, 0.87);
9 | background-color: #242424;
10 |
11 | font-synthesis: none;
12 | text-rendering: optimizeLegibility;
13 | -webkit-font-smoothing: antialiased;
14 | -moz-osx-font-smoothing: grayscale;
15 | -webkit-text-size-adjust: 100%;
16 | }
17 |
18 | a {
19 | font-weight: 500;
20 | color: #646cff;
21 | text-decoration: inherit;
22 | }
23 | a:hover {
24 | color: #535bf2;
25 | }
26 |
27 | body {
28 | margin: 0;
29 | display: flex;
30 | place-items: center;
31 | min-width: 320px;
32 | min-height: 100vh;
33 | }
34 |
35 | h1 {
36 | font-size: 3.2em;
37 | line-height: 1.1;
38 | }
39 |
40 | button {
41 | border-radius: 8px;
42 | border: 1px solid transparent;
43 | padding: 0.6em 1.2em;
44 | font-size: 1em;
45 | font-weight: 500;
46 | font-family: inherit;
47 | background-color: #1a1a1a;
48 | cursor: pointer;
49 | transition: border-color 0.25s;
50 | }
51 | button:hover {
52 | border-color: #646cff;
53 | }
54 | button:focus,
55 | button:focus-visible {
56 | outline: 4px auto -webkit-focus-ring-color;
57 | }
58 |
59 | @media (prefers-color-scheme: light) {
60 | :root {
61 | color: #213547;
62 | background-color: #ffffff;
63 | }
64 | a:hover {
65 | color: #747bff;
66 | }
67 | button {
68 | background-color: #f9f9f9;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/6_HTTP_REACT/http/src/index.css:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
3 | font-size: 16px;
4 | line-height: 24px;
5 | font-weight: 400;
6 |
7 | color-scheme: light dark;
8 | color: rgba(255, 255, 255, 0.87);
9 | background-color: #242424;
10 |
11 | font-synthesis: none;
12 | text-rendering: optimizeLegibility;
13 | -webkit-font-smoothing: antialiased;
14 | -moz-osx-font-smoothing: grayscale;
15 | -webkit-text-size-adjust: 100%;
16 | }
17 |
18 | a {
19 | font-weight: 500;
20 | color: #646cff;
21 | text-decoration: inherit;
22 | }
23 | a:hover {
24 | color: #535bf2;
25 | }
26 |
27 | body {
28 | margin: 0;
29 | display: flex;
30 | place-items: center;
31 | min-width: 320px;
32 | min-height: 100vh;
33 | }
34 |
35 | h1 {
36 | font-size: 3.2em;
37 | line-height: 1.1;
38 | }
39 |
40 | button {
41 | border-radius: 8px;
42 | border: 1px solid transparent;
43 | padding: 0.6em 1.2em;
44 | font-size: 1em;
45 | font-weight: 500;
46 | font-family: inherit;
47 | background-color: #1a1a1a;
48 | cursor: pointer;
49 | transition: border-color 0.25s;
50 | }
51 | button:hover {
52 | border-color: #646cff;
53 | }
54 | button:focus,
55 | button:focus-visible {
56 | outline: 4px auto -webkit-focus-ring-color;
57 | }
58 |
59 | @media (prefers-color-scheme: light) {
60 | :root {
61 | color: #213547;
62 | background-color: #ffffff;
63 | }
64 | a:hover {
65 | color: #747bff;
66 | }
67 | button {
68 | background-color: #f9f9f9;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/7_ROUTER/router/src/index.css:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
3 | font-size: 16px;
4 | line-height: 24px;
5 | font-weight: 400;
6 |
7 | color-scheme: light dark;
8 | color: rgba(255, 255, 255, 0.87);
9 | background-color: #242424;
10 |
11 | font-synthesis: none;
12 | text-rendering: optimizeLegibility;
13 | -webkit-font-smoothing: antialiased;
14 | -moz-osx-font-smoothing: grayscale;
15 | -webkit-text-size-adjust: 100%;
16 | }
17 |
18 | a {
19 | font-weight: 500;
20 | color: #646cff;
21 | text-decoration: inherit;
22 | }
23 | a:hover {
24 | color: #535bf2;
25 | }
26 |
27 | body {
28 | margin: 0;
29 | display: flex;
30 | place-items: center;
31 | min-width: 320px;
32 | min-height: 100vh;
33 | }
34 |
35 | h1 {
36 | font-size: 3.2em;
37 | line-height: 1.1;
38 | }
39 |
40 | button {
41 | border-radius: 8px;
42 | border: 1px solid transparent;
43 | padding: 0.6em 1.2em;
44 | font-size: 1em;
45 | font-weight: 500;
46 | font-family: inherit;
47 | background-color: #1a1a1a;
48 | cursor: pointer;
49 | transition: border-color 0.25s;
50 | }
51 | button:hover {
52 | border-color: #646cff;
53 | }
54 | button:focus,
55 | button:focus-visible {
56 | outline: 4px auto -webkit-focus-ring-color;
57 | }
58 |
59 | @media (prefers-color-scheme: light) {
60 | :root {
61 | color: #213547;
62 | background-color: #ffffff;
63 | }
64 | a:hover {
65 | color: #747bff;
66 | }
67 | button {
68 | background-color: #f9f9f9;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/8_CONTEXT_API/context/src/index.css:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
3 | font-size: 16px;
4 | line-height: 24px;
5 | font-weight: 400;
6 |
7 | color-scheme: light dark;
8 | color: rgba(255, 255, 255, 0.87);
9 | background-color: #242424;
10 |
11 | font-synthesis: none;
12 | text-rendering: optimizeLegibility;
13 | -webkit-font-smoothing: antialiased;
14 | -moz-osx-font-smoothing: grayscale;
15 | -webkit-text-size-adjust: 100%;
16 | }
17 |
18 | a {
19 | font-weight: 500;
20 | color: #646cff;
21 | text-decoration: inherit;
22 | }
23 | a:hover {
24 | color: #535bf2;
25 | }
26 |
27 | body {
28 | margin: 0;
29 | display: flex;
30 | place-items: center;
31 | min-width: 320px;
32 | min-height: 100vh;
33 | }
34 |
35 | h1 {
36 | font-size: 3.2em;
37 | line-height: 1.1;
38 | }
39 |
40 | button {
41 | border-radius: 8px;
42 | border: 1px solid transparent;
43 | padding: 0.6em 1.2em;
44 | font-size: 1em;
45 | font-weight: 500;
46 | font-family: inherit;
47 | background-color: #1a1a1a;
48 | cursor: pointer;
49 | transition: border-color 0.25s;
50 | }
51 | button:hover {
52 | border-color: #646cff;
53 | }
54 | button:focus,
55 | button:focus-visible {
56 | outline: 4px auto -webkit-focus-ring-color;
57 | }
58 |
59 | @media (prefers-color-scheme: light) {
60 | :root {
61 | color: #213547;
62 | background-color: #ffffff;
63 | }
64 | a:hover {
65 | color: #747bff;
66 | }
67 | button {
68 | background-color: #f9f9f9;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/2_FUNDAMENTOS/fundamentos_react/src/index.css:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
3 | font-size: 16px;
4 | line-height: 24px;
5 | font-weight: 400;
6 |
7 | color-scheme: light dark;
8 | color: rgba(255, 255, 255, 0.87);
9 | background-color: #242424;
10 |
11 | font-synthesis: none;
12 | text-rendering: optimizeLegibility;
13 | -webkit-font-smoothing: antialiased;
14 | -moz-osx-font-smoothing: grayscale;
15 | -webkit-text-size-adjust: 100%;
16 | }
17 |
18 | a {
19 | font-weight: 500;
20 | color: #646cff;
21 | text-decoration: inherit;
22 | }
23 | a:hover {
24 | color: #535bf2;
25 | }
26 |
27 | body {
28 | margin: 0;
29 | display: flex;
30 | place-items: center;
31 | min-width: 320px;
32 | min-height: 100vh;
33 | }
34 |
35 | h1 {
36 | font-size: 3.2em;
37 | line-height: 1.1;
38 | }
39 |
40 | button {
41 | border-radius: 8px;
42 | border: 1px solid transparent;
43 | padding: 0.6em 1.2em;
44 | font-size: 1em;
45 | font-weight: 500;
46 | font-family: inherit;
47 | background-color: #1a1a1a;
48 | cursor: pointer;
49 | transition: border-color 0.25s;
50 | }
51 | button:hover {
52 | border-color: #646cff;
53 | }
54 | button:focus,
55 | button:focus-visible {
56 | outline: 4px auto -webkit-focus-ring-color;
57 | }
58 |
59 | @media (prefers-color-scheme: light) {
60 | :root {
61 | color: #213547;
62 | background-color: #ffffff;
63 | }
64 | a:hover {
65 | color: #747bff;
66 | }
67 | button {
68 | background-color: #f9f9f9;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/3_AVANCANDO_EM_REACT/avancando/src/index.css:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
3 | font-size: 16px;
4 | line-height: 24px;
5 | font-weight: 400;
6 |
7 | color-scheme: light dark;
8 | color: rgba(255, 255, 255, 0.87);
9 | background-color: #242424;
10 |
11 | font-synthesis: none;
12 | text-rendering: optimizeLegibility;
13 | -webkit-font-smoothing: antialiased;
14 | -moz-osx-font-smoothing: grayscale;
15 | -webkit-text-size-adjust: 100%;
16 | }
17 |
18 | a {
19 | font-weight: 500;
20 | color: #646cff;
21 | text-decoration: inherit;
22 | }
23 | a:hover {
24 | color: #535bf2;
25 | }
26 |
27 | body {
28 | margin: 0;
29 | display: flex;
30 | place-items: center;
31 | min-width: 320px;
32 | min-height: 100vh;
33 | }
34 |
35 | h1 {
36 | font-size: 3.2em;
37 | line-height: 1.1;
38 | }
39 |
40 | button {
41 | border-radius: 8px;
42 | border: 1px solid transparent;
43 | padding: 0.6em 1.2em;
44 | font-size: 1em;
45 | font-weight: 500;
46 | font-family: inherit;
47 | background-color: #1a1a1a;
48 | cursor: pointer;
49 | transition: border-color 0.25s;
50 | }
51 | button:hover {
52 | border-color: #646cff;
53 | }
54 | button:focus,
55 | button:focus-visible {
56 | outline: 4px auto -webkit-focus-ring-color;
57 | }
58 |
59 | @media (prefers-color-scheme: light) {
60 | :root {
61 | color: #213547;
62 | background-color: #ffffff;
63 | }
64 | a:hover {
65 | color: #747bff;
66 | }
67 | button {
68 | background-color: #f9f9f9;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/9_HOOKS/hooks/src/routes/Home.jsx:
--------------------------------------------------------------------------------
1 | import HookUseEffect from "../components/HookUseEffect";
2 | import HookUseReducer from "../components/HookUseReducer";
3 | import HookUseState from "../components/HookUseState";
4 |
5 | import HookUseRef from "../components/HookUseRef";
6 |
7 | // useContext
8 | import { useContext } from "react";
9 | import { SomeContext } from "../components/HookUseContext";
10 | import HookUseCallback from "../components/HookUseCallback";
11 | import HookUseMemo from "../components/HookUseMemo";
12 | import HookUseLayoutEffect from "../components/HookUseLayoutEffect";
13 | import HookUseImperativeHandle from "../components/HookUseImperativeHandle";
14 | import HookCustom from "../components/HookCustom";
15 |
16 | const Home = () => {
17 | const { contextValue } = useContext(SomeContext);
18 |
19 | return (
20 |
21 |
Home
22 | {/* 1 - useState */}
23 |
24 | {/* 2 - useReducer */}
25 |
26 | {/* 3 - useEffect */}
27 |
28 | {/* 4 - useContext */}
29 |
useContext
30 |
Valor do context: {contextValue}
31 | {/* 5 - useRef */}
32 |
33 | {/* 6 - useCallback */}
34 |
35 | {/* 7 - useMemo */}
36 |
37 | {/* 8 - useLayoutEffect */}
38 |
39 | {/* 9 - useImperativeHandle */}
40 |
41 | {/* 10 - custom hook */}
42 |
43 |
44 | );
45 | };
46 |
47 | export default Home;
48 |
--------------------------------------------------------------------------------
/7_ROUTER/router/src/main.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom/client";
3 | import App from "./App";
4 | import "./index.css";
5 |
6 | import {
7 | createBrowserRouter,
8 | RouterProvider,
9 | Route,
10 | Navigate,
11 | } from "react-router-dom";
12 |
13 | // 2 - pagina de erro
14 | import ErrorPage from "./routes/ErrorPage";
15 |
16 | // 3 - criando e configurando novas paginas
17 | import Contact from "./routes/Contact";
18 |
19 | // 4 - componente base
20 | import Home from "./routes/Home";
21 |
22 | // 9 - rotas dinâmicas
23 | import Product from "./routes/Product";
24 |
25 | // 10 - nested routes
26 | import Info from "./routes/Info";
27 |
28 | // 13 - search params
29 | import Search from "./routes/Search";
30 |
31 | const router = createBrowserRouter([
32 | {
33 | path: "/",
34 | element: ,
35 | errorElement: ,
36 | // 4 - componente base para páginas
37 | children: [
38 | {
39 | path: "/",
40 | element: ,
41 | },
42 | {
43 | path: "contact",
44 | element: ,
45 | },
46 | // 9 - rotas dinâmicas
47 | {
48 | path: "products/:id",
49 | element: ,
50 | },
51 | // 10 - nested routes
52 | {
53 | path: "products/:id/info",
54 | element: ,
55 | },
56 | // 13 - search params
57 | {
58 | path: "search",
59 | element: ,
60 | },
61 | // 14 - redirect
62 | {
63 | path: "teste",
64 | element: ,
65 | },
66 | ],
67 | },
68 | // {
69 | // path: "contact",
70 | // element: ,
71 | // },
72 | ]);
73 |
74 | ReactDOM.createRoot(document.getElementById("root")).render(
75 |
76 |
77 |
78 | );
79 |
--------------------------------------------------------------------------------
/6_HTTP_REACT/http/hooks/useFetch.js:
--------------------------------------------------------------------------------
1 | import { useState, useEffect } from "react";
2 |
3 | // 4 - custom hook
4 | export const useFetch = (url) => {
5 | const [data, setData] = useState(null);
6 |
7 | // 5 - refatorando post
8 | const [config, setConfig] = useState(null);
9 | const [method, setMethod] = useState(null);
10 | const [callFetch, setCallFetch] = useState(false);
11 |
12 | // 6 - loading
13 | const [loading, setLoading] = useState(false);
14 |
15 | // 7 - tratando erros
16 | const [error, setError] = useState(null);
17 |
18 | const httpConfig = (data, method) => {
19 | if (method === "POST") {
20 | setConfig({
21 | method,
22 | headers: {
23 | "Content-type": "application/json",
24 | },
25 | body: JSON.stringify(data),
26 | });
27 |
28 | setMethod(method);
29 | }
30 | };
31 |
32 | useEffect(() => {
33 | // 6 - loading
34 | setLoading(true);
35 |
36 | const fetchData = async () => {
37 | // 7 - tratando erros
38 | try {
39 | const res = await fetch(url);
40 |
41 | const json = await res.json();
42 |
43 | setData(json);
44 | } catch (error) {
45 | console.log(error.message);
46 |
47 | setError("Houve algum erro ao carregar os dados!");
48 | }
49 |
50 | // 6 - loading
51 | setLoading(false);
52 | };
53 |
54 | fetchData();
55 | }, [url, callFetch]);
56 |
57 | // 5 - refatorando post
58 | useEffect(() => {
59 | const httpRequest = async () => {
60 | let json;
61 |
62 | if (method === "POST") {
63 | let fetchOptions = [url, config];
64 |
65 | const res = await fetch(...fetchOptions);
66 |
67 | json = await res.json();
68 | }
69 |
70 | setCallFetch(json);
71 | };
72 |
73 | httpRequest();
74 | }, [config, method, url]);
75 |
76 | return { data, httpConfig, loading, error };
77 | };
78 |
--------------------------------------------------------------------------------
/9_HOOKS/hooks/src/components/HookUseReducer.jsx:
--------------------------------------------------------------------------------
1 | import { useReducer, useState } from "react";
2 |
3 | const HookUseReducer = () => {
4 | // 1 - começando com o useReducer
5 | const [number, dispatch] = useReducer((state, action) => {
6 | return Math.random(state);
7 | });
8 |
9 | // 2 - avançando no useReducer
10 | const initialTasks = [
11 | { id: 1, text: "Fazer alguma coisa" },
12 | { id: 2, text: "Fazer outra coisa" },
13 | ];
14 |
15 | const taskReducer = (state, action) => {
16 | switch (action.type) {
17 | case "ADD":
18 | const newTask = {
19 | id: Math.random(),
20 | text: taskText,
21 | };
22 |
23 | setTaskText("");
24 |
25 | return [...state, newTask];
26 | case "DELETE":
27 | return state.filter((task) => task.id !== action.id);
28 | default:
29 | return state;
30 | }
31 | };
32 |
33 | const [taskText, setTaskText] = useState("");
34 | const [tasks, dispatchTasks] = useReducer(taskReducer, initialTasks);
35 |
36 | const handleSubmit = (e) => {
37 | e.preventDefault();
38 |
39 | dispatchTasks({ type: "ADD" });
40 | };
41 |
42 | const removeTask = (id) => {
43 | dispatchTasks({ type: "DELETE", id });
44 | };
45 |
46 | return (
47 |
48 |
useReducer
49 |
Número: {number}
50 |
51 |
Tarefas:
52 |
60 | {tasks.map((task) => (
61 |
removeTask(task.id)}>
62 | {task.text}
63 |
64 | ))}
65 |
66 |
67 | );
68 | };
69 |
70 | export default HookUseReducer;
71 |
--------------------------------------------------------------------------------
/6_HTTP_REACT/http/data/db.json:
--------------------------------------------------------------------------------
1 | {
2 | "products": [
3 | {
4 | "name": "teste",
5 | "price": "12",
6 | "id": 4
7 | },
8 | {
9 | "name": "capa de chuva",
10 | "price": "50.50",
11 | "id": 5
12 | },
13 | {
14 | "name": "teclado",
15 | "price": "110",
16 | "id": 6
17 | },
18 | {
19 | "name": "cadeira",
20 | "price": "200",
21 | "id": 7
22 | },
23 | {
24 | "name": "mouse",
25 | "price": "60",
26 | "id": 8
27 | },
28 | {
29 | "name": "suporte monitor",
30 | "price": "120",
31 | "id": 9
32 | },
33 | {
34 | "name": "cabo hdmi",
35 | "price": "10",
36 | "id": 11
37 | },
38 | {
39 | "name": "suporte microfone",
40 | "price": "60",
41 | "id": 12
42 | },
43 | {
44 | "name": "suporte microfone 2",
45 | "price": "70",
46 | "id": 14
47 | },
48 | {
49 | "name": "suporte microfone 3",
50 | "price": "75",
51 | "id": 15
52 | },
53 | {
54 | "name": "teste",
55 | "price": "1",
56 | "id": 16
57 | },
58 | {
59 | "name": "teste",
60 | "price": "2",
61 | "id": 17
62 | },
63 | {
64 | "name": "adsas",
65 | "price": "1",
66 | "id": 18
67 | },
68 | {
69 | "name": "teste",
70 | "price": "5",
71 | "id": 19
72 | },
73 | {
74 | "name": "teste",
75 | "price": "5",
76 | "id": 20
77 | },
78 | {
79 | "name": "teste",
80 | "price": "5",
81 | "id": 21
82 | },
83 | {
84 | "name": "teste",
85 | "price": "5",
86 | "id": 22
87 | },
88 | {
89 | "name": "teste",
90 | "price": "5",
91 | "id": 23
92 | },
93 | {
94 | "name": "teste",
95 | "price": "5",
96 | "id": 24
97 | },
98 | {
99 | "name": "xaxa",
100 | "price": "1",
101 | "id": 25
102 | }
103 | ]
104 | }
--------------------------------------------------------------------------------
/7_ROUTER/router/src/hooks/useFetch.js:
--------------------------------------------------------------------------------
1 | import { useState, useEffect } from "react";
2 |
3 | // 4 - custom hook
4 | export const useFetch = (url) => {
5 | const [data, setData] = useState(null);
6 |
7 | // 5 - refatorando post
8 | const [config, setConfig] = useState(null);
9 | const [method, setMethod] = useState(null);
10 | const [callFetch, setCallFetch] = useState(false);
11 |
12 | // 6 - loading
13 | const [loading, setLoading] = useState(false);
14 |
15 | // 7 - tratando erros
16 | const [error, setError] = useState(null);
17 |
18 | // 8 - desafio 6
19 | const [itemId, setItemId] = useState(null);
20 |
21 | const httpConfig = (data, method) => {
22 | if (method === "POST") {
23 | setConfig({
24 | method,
25 | headers: {
26 | "Content-type": "application/json",
27 | },
28 | body: JSON.stringify(data),
29 | });
30 |
31 | setMethod(method);
32 | } else if (method === "DELETE") {
33 | setConfig({
34 | method,
35 | headers: {
36 | "Content-type": "application/json",
37 | },
38 | });
39 |
40 | setMethod(method);
41 | setItemId(data);
42 | }
43 | };
44 |
45 | useEffect(() => {
46 | const fetchData = async () => {
47 | // 6 - loading
48 | setLoading(true);
49 |
50 | try {
51 | const res = await fetch(url);
52 |
53 | const json = await res.json();
54 |
55 | setData(json);
56 | } catch (error) {
57 | console.log(error.message);
58 |
59 | setError("Houve algum erro ao carregar os dados!");
60 | }
61 |
62 | setLoading(false);
63 | };
64 |
65 | fetchData();
66 | }, [url, callFetch]);
67 |
68 | // 5 - refatorando post
69 | useEffect(() => {
70 | const httpRequest = async () => {
71 | let json;
72 |
73 | if (method === "POST") {
74 | let fetchOptions = [url, config];
75 |
76 | const res = await fetch(...fetchOptions);
77 |
78 | json = await res.json();
79 | } else if (method === "DELETE") {
80 | const deleteUrl = `${url}/${itemId}`;
81 |
82 | const res = await fetch(deleteUrl, config);
83 |
84 | json = await res.json();
85 | }
86 |
87 | setCallFetch(json);
88 | };
89 |
90 | httpRequest();
91 | }, [config, method, url]);
92 |
93 | return { data, httpConfig, loading, error };
94 | };
95 |
--------------------------------------------------------------------------------
/5_FORM_REACT/form/src/components/MyForm.jsx:
--------------------------------------------------------------------------------
1 | import "./MyForm.css";
2 |
3 | import { useState } from "react";
4 |
5 | const MyForm = ({ userName, userEmail }) => {
6 | // 3 - gerenciamento de dados
7 | const [name, setName] = useState(userName);
8 | const [email, setEmail] = useState(userEmail);
9 |
10 | // 8 - textarea
11 | const [bio, setBio] = useState();
12 |
13 | // 9 - select
14 | const [role, setRole] = useState();
15 |
16 | const handleName = (e) => {
17 | setName(e.target.value);
18 | };
19 |
20 | console.log(name, email);
21 |
22 | // 5 - envio de formulário
23 | const handleSubmit = (e) => {
24 | e.preventDefault();
25 | console.log("Enviando o formulário");
26 | console.log(name, email, bio, role);
27 |
28 | // validacao
29 | // envio
30 |
31 | // 7 - limpar form
32 | setName("");
33 | setEmail("");
34 |
35 | setBio("");
36 | };
37 |
38 | return (
39 |
40 | {/* 5 - envio de formulário */}
41 | {/* 1 - criação de form */}
42 |
92 |
93 | );
94 | };
95 |
96 | export default MyForm;
97 |
--------------------------------------------------------------------------------
/6_HTTP_REACT/http/src/App.jsx:
--------------------------------------------------------------------------------
1 | import { useState, useEffect } from "react";
2 | import "./App.css";
3 |
4 | // para checar erros, deixar URL vazia
5 | const url = "http://localhost:3000/products";
6 |
7 | import { useFetch } from "../hooks/useFetch";
8 |
9 | function App() {
10 | // / 1 - resgatando dados
11 | const [products, setProducts] = useState([]);
12 |
13 | // 4 custom hook
14 | const { data: items, httpConfig, loading, error } = useFetch(url);
15 |
16 | // useEffect(() => {
17 | // async function fetchData() {
18 | // const res = await fetch(url);
19 |
20 | // const data = await res.json();
21 |
22 | // setProducts(data);
23 | // }
24 |
25 | // fetchData();
26 | // }, []);
27 |
28 | // 2 - enviando dados
29 | const [name, setName] = useState("");
30 | const [price, setPrice] = useState("");
31 |
32 | const handleSubmit = async (e) => {
33 | e.preventDefault();
34 |
35 | const product = {
36 | name,
37 | price,
38 | };
39 |
40 | // const res = await fetch(url, {
41 | // method: "POST",
42 | // headers: {
43 | // "Content-Type": "application/json",
44 | // },
45 | // body: JSON.stringify(product),
46 | // });
47 |
48 | // // 3 - carregamento dinâmico
49 | // const addedProduct = await res.json();
50 |
51 | // setProducts((prevProducts) => [...prevProducts, addedProduct]);
52 |
53 | // 5 - refatorando post
54 | httpConfig(product, "POST");
55 | };
56 |
57 | return (
58 |
103 | );
104 | }
105 |
106 | export default App;
107 |
--------------------------------------------------------------------------------
/3_AVANCANDO_EM_REACT/avancando/src/App.jsx:
--------------------------------------------------------------------------------
1 | import "./App.css";
2 |
3 | // 2 - imagem em assets
4 | import night from "./assets/night.jpg";
5 |
6 | // 3 - useState
7 | import Data from "./components/Data";
8 |
9 | // 4 - render de lista
10 | import ListRender from "./components/ListRender";
11 |
12 | // 7 - renderizacao condicional
13 | import ConditionalRender from "./components/ConditionalRender";
14 |
15 | // 8 - props
16 | import ShowUserName from "./components/ShowUserName";
17 | import CarDetails from "./components/CarDetails";
18 |
19 | // 11 - renderizacao de lista
20 | const cars = [
21 | { id: 1, brand: "Ferrari", color: "Amarelo", km: 0 },
22 | { id: 2, brand: "KIA", color: "Branco", km: 200000 },
23 | { id: 3, brand: "Renault", color: "Azul", km: 32000 },
24 | ];
25 |
26 | // 12 - fragments
27 | import Fragment from "./components/Fragment";
28 |
29 | // 13 - children prop
30 | import Container from "./components/Container";
31 |
32 | // 14 - funcao em prop
33 | import ExecuteFunction from "./components/ExecuteFunction";
34 |
35 | // 15 - state lift
36 | import { useState } from "react";
37 |
38 | import MessageState from "./components/MessageState";
39 | import ChangeMessageState from "./components/ChangeMessageState";
40 |
41 | function App() {
42 | // 14 - funcao em prop
43 | function showMessage() {
44 | console.log("Evento do componente pai");
45 | }
46 |
47 | // 15 - state lift
48 | const [message, setMessage] = useState();
49 |
50 | const handleMessage = (msg) => {
51 | setMessage(msg);
52 | };
53 |
54 | return (
55 |
56 |
Avançando em React
57 | {/* 1 - Imagem em public */}
58 |

59 | {/* 2 - Imagem em assets */}
60 |

61 | {/* 3 - useState */}
62 |
63 | {/* 4 - render de lista */}
64 |
65 | {/* 7 - render condicional */}
66 |
67 | {/* 8 - props */}
68 |
69 | {/* 9 - destructuring em props */}
70 |
71 | {/* 10 - reaproveitamento de componentes */}
72 |
73 |
74 | {/* 11 - renderizacao de lista */}
75 | {cars.map((car) => (
76 |
82 | ))}
83 | {/* 12 - Fragments */}
84 |
85 | {/* 13 - children prop */}
86 |
87 | Eu sou do componente superior
88 |
89 |
90 |
93 |
94 | {/* 14 - funcao em prop */}
95 |
96 | {/* 15 - state lift */}
97 |
98 |
99 |
100 | );
101 | }
102 |
103 | export default App;
104 |
--------------------------------------------------------------------------------
/1_INTRO/intro/src/assets/react.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/4_CSS_REACT/css/src/assets/react.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/7_ROUTER/router/src/assets/react.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/9_HOOKS/hooks/src/assets/react.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/5_FORM_REACT/form/src/assets/react.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/6_HTTP_REACT/http/src/assets/react.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/8_CONTEXT_API/context/src/assets/react.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/2_FUNDAMENTOS/fundamentos_react/src/assets/react.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/3_AVANCANDO_EM_REACT/avancando/src/assets/react.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------