ReactJS
Projeto Next.js
$ npx create-next-app
✔ What is your project named? invest-app
✔ Would you like to use TypeScript with this project? No / Yes
✔ Would you like to use ESLint with this project? No / Yes
✔ Would you like to use Tailwind CSS with this project? No / Yes
✔ Would you like to use `src/` directory with this project? No / Yes
✔ Use App Router (recommended)? No / Yes
✔ Would you like to customize the default import alias? No / Yes
Creating a new Next.js app in /codes/react/introduction/invest-app.
 
Using npm.
 
Initializing project with template: app-tw
 
 
Installing dependencies:
- react
- react-dom
- next
- tailwindcss
- postcss
- autoprefixer
- eslint
- eslint-config-next
 
 
added 323 packages, and audited 324 packages in 28s
 
117 packages are looking for funding
  run `npm fund` for details
 
found 0 vulnerabilities$ npx create-next-app
✔ What is your project named? invest-app
✔ Would you like to use TypeScript with this project? No / Yes
✔ Would you like to use ESLint with this project? No / Yes
✔ Would you like to use Tailwind CSS with this project? No / Yes
✔ Would you like to use `src/` directory with this project? No / Yes
✔ Use App Router (recommended)? No / Yes
✔ Would you like to customize the default import alias? No / Yes
Creating a new Next.js app in /codes/react/introduction/invest-app.
 
Using npm.
 
Initializing project with template: app-tw
 
 
Installing dependencies:
- react
- react-dom
- next
- tailwindcss
- postcss
- autoprefixer
- eslint
- eslint-config-next
 
 
added 323 packages, and audited 324 packages in 28s
 
117 packages are looking for funding
  run `npm fund` for details
 
found 0 vulnerabilitiesArquivos
invest-app
├── README.md
├── jsconfig.json
├── next.config.js
├── package-lock.json
├── package.json
├── postcss.config.js
├── public
│   ├── next.svg
│   └── vercel.svg
├── src
│   └── app
│       ├── favicon.ico
│       ├── globals.css
│       ├── layout.js
│       └── page.js
└── tailwind.config.jsArquivos
invest-app
├── README.md
├── jsconfig.json
├── next.config.js
├── package-lock.json
├── package.json
├── postcss.config.js
├── public
│   ├── next.svg
│   └── vercel.svg
├── src
│   └── app
│       ├── favicon.ico
│       ├── globals.css
│       ├── layout.js
│       └── page.js
└── tailwind.config.jsComponentes
Multiplataforma

- Web: react-dom (ReactJS), react-native-dom (React Native)
- Mobile: android-native, ios-native (React Native)
- Desktop: react-native-windows, proton-native (React Native)
- TV: react-native-tvos (React Native)
- Outras

Declaração
Function Component
export default function Home() {
  return <h1>Investimentos</h1>
}export default function Home() {
  return <h1>Investimentos</h1>
}Class Component
export default class App extends React.Component {
  render() {
    return <h1>Investimentos</h1>;
  }
}export default class App extends React.Component {
  render() {
    return <h1>Investimentos</h1>;
  }
}Fragment
/codes/react/introduction/invest-app/src/app/page.jsx
export default function Home() {
  return (
    <>
      <h1 className="text-center text-2xl my-12 font-bold">Investimentos</h1>
 
      <div className="investments grid grid-cols-3 gap-3">
      </div>
    </>
  );
}/codes/react/introduction/invest-app/src/app/page.jsx
export default function Home() {
  return (
    <>
      <h1 className="text-center text-2xl my-12 font-bold">Investimentos</h1>
 
      <div className="investments grid grid-cols-3 gap-3">
      </div>
    </>
  );
}JavaScript XML (JSX)
Regras
- Return a single root element
- Close all the tags
- camelCase all most of the things!
Curly Braces
- Passing strings with quotes
- Text and Attributes
- double curlies
Exemplo
/codes/react/introduction/invest-app/src/app/page.jsx
import { investments } from '@/data/seed';
import { formatCurrency, formatDate } from '@/lib/format';
 
export default function Home() {
  const investment = {
    id: 'b9f2414d-b8dd-484d-8179-83383d10a3fd',
    name: 'Tesouro Selic 2029',
    value: 10050,
    origin: 'Tesouro Nacional',
    category: 'Pós',
    created_at: '2023-08-22T00:00:00-03:00',
    interest: '100% Selic',
  };
 
  return (
    <>
      <h1 className="text-center text-2xl my-12 font-bold">Investimentos</h1>
 
      <div className="investments grid grid-cols-3 gap-3">
        <div className="bg-white shadow-md rounded-lg p-4 relative">
          <div className="flex justify-between items-center">
            <h3 className="investment-name text-lg font-semibold text-gray-700">
              {investment.name}
            </h3>
            <p className="investment-value text-lg font-semibold text-gray-700">
              {formatCurrency(investment.value / 100)}
            </p>
          </div>
          <div className="mt-4">
            <p className="text-sm text-gray-500">
              <span className="font-bold mr-1">Origem:</span>
              <span className="investment-origin">{investment.origin}</span>
            </p>
            <p className="text-sm text-gray-500">
              <span className="font-bold mr-1">Categoria:</span>
              <span className="investment-category">{investment.category}</span>
            </p>
            <p className="text-sm text-gray-500">
              <span className="font-bold mr-1">Taxa:</span>
              <span className="investment-interest">{investment.interest}</span>
            </p>
            <p className="text-sm text-gray-500">
              <span className="font-bold mr-1">Data:</span>
              <span className="investment-created_at">
                {formatDate(investment.created_at)}
              </span>
            </p>
          </div>
        </div>
      </div>
    </>
  );
}/codes/react/introduction/invest-app/src/app/page.jsx
import { investments } from '@/data/seed';
import { formatCurrency, formatDate } from '@/lib/format';
 
export default function Home() {
  const investment = {
    id: 'b9f2414d-b8dd-484d-8179-83383d10a3fd',
    name: 'Tesouro Selic 2029',
    value: 10050,
    origin: 'Tesouro Nacional',
    category: 'Pós',
    created_at: '2023-08-22T00:00:00-03:00',
    interest: '100% Selic',
  };
 
  return (
    <>
      <h1 className="text-center text-2xl my-12 font-bold">Investimentos</h1>
 
      <div className="investments grid grid-cols-3 gap-3">
        <div className="bg-white shadow-md rounded-lg p-4 relative">
          <div className="flex justify-between items-center">
            <h3 className="investment-name text-lg font-semibold text-gray-700">
              {investment.name}
            </h3>
            <p className="investment-value text-lg font-semibold text-gray-700">
              {formatCurrency(investment.value / 100)}
            </p>
          </div>
          <div className="mt-4">
            <p className="text-sm text-gray-500">
              <span className="font-bold mr-1">Origem:</span>
              <span className="investment-origin">{investment.origin}</span>
            </p>
            <p className="text-sm text-gray-500">
              <span className="font-bold mr-1">Categoria:</span>
              <span className="investment-category">{investment.category}</span>
            </p>
            <p className="text-sm text-gray-500">
              <span className="font-bold mr-1">Taxa:</span>
              <span className="investment-interest">{investment.interest}</span>
            </p>
            <p className="text-sm text-gray-500">
              <span className="font-bold mr-1">Data:</span>
              <span className="investment-created_at">
                {formatDate(investment.created_at)}
              </span>
            </p>
          </div>
        </div>
      </div>
    </>
  );
}Propriedades
props
/codes/react/introduction/invest-app/src/app/page.jsx
import InvestmentCard from '@/components/InvestmentCard';
 
export default function Home() {
  const investment = {
    id: 'b9f2414d-b8dd-484d-8179-83383d10a3fd',
    name: 'Tesouro Selic 2029',
    value: 10050,
    origin: 'Tesouro Nacional',
    category: 'Pós',
    created_at: '2023-08-22T00:00:00-03:00',
    interest: '100% Selic',
  };
 
  return (
    <>
      <h1 className="text-center text-2xl my-12 font-bold">Investimentos</h1>
 
      <div className="investments grid grid-cols-3 gap-3">
        <InvestmentCard investment={investment} />
      </div>
    </>
  );
}/codes/react/introduction/invest-app/src/app/page.jsx
import InvestmentCard from '@/components/InvestmentCard';
 
export default function Home() {
  const investment = {
    id: 'b9f2414d-b8dd-484d-8179-83383d10a3fd',
    name: 'Tesouro Selic 2029',
    value: 10050,
    origin: 'Tesouro Nacional',
    category: 'Pós',
    created_at: '2023-08-22T00:00:00-03:00',
    interest: '100% Selic',
  };
 
  return (
    <>
      <h1 className="text-center text-2xl my-12 font-bold">Investimentos</h1>
 
      <div className="investments grid grid-cols-3 gap-3">
        <InvestmentCard investment={investment} />
      </div>
    </>
  );
}/codes/react/introduction/invest-app/src/components/InvestmentCard.jsx
import { formatCurrency, formatDate } from '@/lib/format';
 
export default function InvestmentCard(props) {
  return (
    <div className="bg-white shadow-md rounded-lg p-4 relative">
      <div className="flex justify-between items-center">
        <h3 className="investment-name text-lg font-semibold text-gray-700">
          {props.investment.name}
        </h3>
        <p className="investment-value text-lg font-semibold text-gray-700">
          {formatCurrency(props.investment.value / 100)}
        </p>
      </div>
      <div className="mt-4">
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Origem:</span>
          <span className="investment-origin">{props.investment.origin}</span>
        </p>
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Categoria:</span>
          <span className="investment-category">{props.investment.category}</span>
        </p>
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Taxa:</span>
          <span className="investment-interest">{props.investment.interest}</span>
        </p>
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Data:</span>
          <span className="investment-created_at">
            {formatDate(props.investment.created_at)}
          </span>
        </p>
      </div>
    </div>
  );
}/codes/react/introduction/invest-app/src/components/InvestmentCard.jsx
import { formatCurrency, formatDate } from '@/lib/format';
 
export default function InvestmentCard(props) {
  return (
    <div className="bg-white shadow-md rounded-lg p-4 relative">
      <div className="flex justify-between items-center">
        <h3 className="investment-name text-lg font-semibold text-gray-700">
          {props.investment.name}
        </h3>
        <p className="investment-value text-lg font-semibold text-gray-700">
          {formatCurrency(props.investment.value / 100)}
        </p>
      </div>
      <div className="mt-4">
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Origem:</span>
          <span className="investment-origin">{props.investment.origin}</span>
        </p>
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Categoria:</span>
          <span className="investment-category">{props.investment.category}</span>
        </p>
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Taxa:</span>
          <span className="investment-interest">{props.investment.interest}</span>
        </p>
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Data:</span>
          <span className="investment-created_at">
            {formatDate(props.investment.created_at)}
          </span>
        </p>
      </div>
    </div>
  );
}Object (double curlies)
/codes/react/introduction/invest-app/src/app/page.jsx
<InvestmentCard
  id="b9f2414d-b8dd-484d-8179-83383d10a3fd"
  name={`Tesouro Selic ${2029}`}
  value={10050}
  origin="Tesouro Nacional"
  category="Pós"
  created_at="2023-08-22T00:00:00-03:00"
  interest="100% Selic"
/>/codes/react/introduction/invest-app/src/app/page.jsx
<InvestmentCard
  id="b9f2414d-b8dd-484d-8179-83383d10a3fd"
  name={`Tesouro Selic ${2029}`}
  value={10050}
  origin="Tesouro Nacional"
  category="Pós"
  created_at="2023-08-22T00:00:00-03:00"
  interest="100% Selic"
/>/codes/react/introduction/invest-app/src/app/page.jsx
<InvestmentCard {{
  id: 'b9f2414d-b8dd-484d-8179-83383d10a3fd',
  name: 'Tesouro Selic 2029',
  value: 10050,
  origin: 'Tesouro Nacional',
  category: 'Pós',
  created_at: '2023-08-22T00:00:00-03:00',
  interest: '100% Selic',
}} />/codes/react/introduction/invest-app/src/app/page.jsx
<InvestmentCard {{
  id: 'b9f2414d-b8dd-484d-8179-83383d10a3fd',
  name: 'Tesouro Selic 2029',
  value: 10050,
  origin: 'Tesouro Nacional',
  category: 'Pós',
  created_at: '2023-08-22T00:00:00-03:00',
  interest: '100% Selic',
}} />/codes/react/introduction/invest-app/src/components/InvestmentCard.jsx
import { formatCurrency, formatDate } from '@/lib/format';
 
export default function InvestmentCard({
  name,
  value,
  origin,
  category,
  interest,
  created_at,
}) {
  return (
    <div className="bg-white shadow-md rounded-lg p-4 relative">
      <div className="flex justify-between items-center">
        <h3 className="investment-name text-lg font-semibold text-gray-700">
          {name}
        </h3>
        <p className="investment-value text-lg font-semibold text-gray-700">
          {formatCurrency(value / 100)}
        </p>
      </div>
      <div className="mt-4">
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Origem:</span>
          <span className="investment-origin">{origin}</span>
        </p>
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Categoria:</span>
          <span className="investment-category">{category}</span>
        </p>
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Taxa:</span>
          <span className="investment-interest">{interest}</span>
        </p>
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Data:</span>
          <span className="investment-created_at">{formatDate(created_at)}</span>
        </p>
      </div>
    </div>
  );
}/codes/react/introduction/invest-app/src/components/InvestmentCard.jsx
import { formatCurrency, formatDate } from '@/lib/format';
 
export default function InvestmentCard({
  name,
  value,
  origin,
  category,
  interest,
  created_at,
}) {
  return (
    <div className="bg-white shadow-md rounded-lg p-4 relative">
      <div className="flex justify-between items-center">
        <h3 className="investment-name text-lg font-semibold text-gray-700">
          {name}
        </h3>
        <p className="investment-value text-lg font-semibold text-gray-700">
          {formatCurrency(value / 100)}
        </p>
      </div>
      <div className="mt-4">
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Origem:</span>
          <span className="investment-origin">{origin}</span>
        </p>
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Categoria:</span>
          <span className="investment-category">{category}</span>
        </p>
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Taxa:</span>
          <span className="investment-interest">{interest}</span>
        </p>
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Data:</span>
          <span className="investment-created_at">{formatDate(created_at)}</span>
        </p>
      </div>
    </div>
  );
}JSX spread syntax
/codes/react/introduction/invest-app/src/app/page.jsx
const investment = {
  id: 'b9f2414d-b8dd-484d-8179-83383d10a3fd',
  name: 'Tesouro Selic 2029',
  value: 10050,
  origin: 'Tesouro Nacional',
  category: 'Pós',
  created_at: '2023-08-22T00:00:00-03:00',
  interest: '100% Selic',
};
 
<InvestmentCard {...investment} />/codes/react/introduction/invest-app/src/app/page.jsx
const investment = {
  id: 'b9f2414d-b8dd-484d-8179-83383d10a3fd',
  name: 'Tesouro Selic 2029',
  value: 10050,
  origin: 'Tesouro Nacional',
  category: 'Pós',
  created_at: '2023-08-22T00:00:00-03:00',
  interest: '100% Selic',
};
 
<InvestmentCard {...investment} />/codes/react/introduction/invest-app/src/components/InvestmentCard.jsx
import { formatCurrency, formatDate } from '@/lib/format';
 
export default function InvestmentCard({
  name,
  value,
  origin,
  category,
  interest,
  created_at,
}) {
  return (
    <div className="bg-white shadow-md rounded-lg p-4 relative">
      <div className="flex justify-between items-center">
        <h3 className="investment-name text-lg font-semibold text-gray-700">
          {name}
        </h3>
        <p className="investment-value text-lg font-semibold text-gray-700">
          {formatCurrency(value / 100)}
        </p>
      </div>
      <div className="mt-4">
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Origem:</span>
          <span className="investment-origin">{origin}</span>
        </p>
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Categoria:</span>
          <span className="investment-category">{category}</span>
        </p>
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Taxa:</span>
          <span className="investment-interest">{interest}</span>
        </p>
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Data:</span>
          <span className="investment-created_at">{formatDate(created_at)}</span>
        </p>
      </div>
    </div>
  );
}/codes/react/introduction/invest-app/src/components/InvestmentCard.jsx
import { formatCurrency, formatDate } from '@/lib/format';
 
export default function InvestmentCard({
  name,
  value,
  origin,
  category,
  interest,
  created_at,
}) {
  return (
    <div className="bg-white shadow-md rounded-lg p-4 relative">
      <div className="flex justify-between items-center">
        <h3 className="investment-name text-lg font-semibold text-gray-700">
          {name}
        </h3>
        <p className="investment-value text-lg font-semibold text-gray-700">
          {formatCurrency(value / 100)}
        </p>
      </div>
      <div className="mt-4">
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Origem:</span>
          <span className="investment-origin">{origin}</span>
        </p>
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Categoria:</span>
          <span className="investment-category">{category}</span>
        </p>
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Taxa:</span>
          <span className="investment-interest">{interest}</span>
        </p>
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Data:</span>
          <span className="investment-created_at">{formatDate(created_at)}</span>
        </p>
      </div>
    </div>
  );
}JSX as children
/codes/react/introduction/invest-app/src/app/page.jsx
const investment = {
  id: 'b9f2414d-b8dd-484d-8179-83383d10a3fd',
  name: 'Tesouro Selic 2029',
  value: 10050,
  origin: 'Tesouro Nacional',
  category: 'Pós',
  created_at: '2023-08-22T00:00:00-03:00',
  interest: '100% Selic',
};
 
<InvestmentCard {...investment}>
  <strong>#</strong>
  {investment.name}
</InvestmentCard>/codes/react/introduction/invest-app/src/app/page.jsx
const investment = {
  id: 'b9f2414d-b8dd-484d-8179-83383d10a3fd',
  name: 'Tesouro Selic 2029',
  value: 10050,
  origin: 'Tesouro Nacional',
  category: 'Pós',
  created_at: '2023-08-22T00:00:00-03:00',
  interest: '100% Selic',
};
 
<InvestmentCard {...investment}>
  <strong>#</strong>
  {investment.name}
</InvestmentCard>/codes/react/introduction/invest-app/src/components/InvestmentCard.jsx
import { formatCurrency, formatDate } from '@/lib/format';
 
export default function InvestmentCard({
  name,
  value,
  origin,
  category,
  interest,
  created_at,
  children
}) {
  return (
    <div className="bg-white shadow-md rounded-lg p-4 relative">
      <div className="flex justify-between items-center">
        <h3 className="investment-name text-lg font-semibold text-gray-700">
          {children}
        </h3>
        <p className="investment-value text-lg font-semibold text-gray-700">
          {formatCurrency(value / 100)}
        </p>
      </div>
      <div className="mt-4">
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Origem:</span>
          <span className="investment-origin">{origin}</span>
        </p>
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Categoria:</span>
          <span className="investment-category">{category}</span>
        </p>
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Taxa:</span>
          <span className="investment-interest">{interest}</span>
        </p>
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Data:</span>
          <span className="investment-created_at">{formatDate(created_at)}</span>
        </p>
      </div>
    </div>
  );
}/codes/react/introduction/invest-app/src/components/InvestmentCard.jsx
import { formatCurrency, formatDate } from '@/lib/format';
 
export default function InvestmentCard({
  name,
  value,
  origin,
  category,
  interest,
  created_at,
  children
}) {
  return (
    <div className="bg-white shadow-md rounded-lg p-4 relative">
      <div className="flex justify-between items-center">
        <h3 className="investment-name text-lg font-semibold text-gray-700">
          {children}
        </h3>
        <p className="investment-value text-lg font-semibold text-gray-700">
          {formatCurrency(value / 100)}
        </p>
      </div>
      <div className="mt-4">
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Origem:</span>
          <span className="investment-origin">{origin}</span>
        </p>
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Categoria:</span>
          <span className="investment-category">{category}</span>
        </p>
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Taxa:</span>
          <span className="investment-interest">{interest}</span>
        </p>
        <p className="text-sm text-gray-500">
          <span className="font-bold mr-1">Data:</span>
          <span className="investment-created_at">{formatDate(created_at)}</span>
        </p>
      </div>
    </div>
  );
}Lista e Chaves
/codes/react/introduction/invest-app/src/data/seed.js
export const investments = [
  {
    id: 'b9f2414d-b8dd-484d-8179-83383d10a3fd',
    name: 'Tesouro Selic 2029',
    value: 10050,
    origin: 'Tesouro Nacional',
    category: 'Pós',
    created_at: '2023-08-22T00:00:00-03:00',
    interest: '100% Selic',
  },
  {
    id: 'bb0a4c9b-8eea-4d79-a248-39c8b846fa9e',
    name: 'Tesouro IPCA 2029',
    value: 10000,
    origin: 'Tesouro Nacional',
    category: 'IPCA',
    created_at: '2023-08-22T00:00:00-03:00',
    interest: 'IPCA + 5,83%',
  },
];/codes/react/introduction/invest-app/src/data/seed.js
export const investments = [
  {
    id: 'b9f2414d-b8dd-484d-8179-83383d10a3fd',
    name: 'Tesouro Selic 2029',
    value: 10050,
    origin: 'Tesouro Nacional',
    category: 'Pós',
    created_at: '2023-08-22T00:00:00-03:00',
    interest: '100% Selic',
  },
  {
    id: 'bb0a4c9b-8eea-4d79-a248-39c8b846fa9e',
    name: 'Tesouro IPCA 2029',
    value: 10000,
    origin: 'Tesouro Nacional',
    category: 'IPCA',
    created_at: '2023-08-22T00:00:00-03:00',
    interest: 'IPCA + 5,83%',
  },
];/codes/react/introduction/invest-app/src/app/page.jsx
import InvestmentCard from '@/components/InvestmentCard';
import { investments } from '@/data/seed';
 
export default function Home() {
  return (
    <>
      <h1 className="text-center text-2xl my-12 font-bold">Investimentos</h1>
 
      <div className="investments grid grid-cols-3 gap-3">
        {investments.map((investment) => (
          <InvestmentCard investment={investment} key={investment.id} />
        ))}
      </div>
    </>
  );
}/codes/react/introduction/invest-app/src/app/page.jsx
import InvestmentCard from '@/components/InvestmentCard';
import { investments } from '@/data/seed';
 
export default function Home() {
  return (
    <>
      <h1 className="text-center text-2xl my-12 font-bold">Investimentos</h1>
 
      <div className="investments grid grid-cols-3 gap-3">
        {investments.map((investment) => (
          <InvestmentCard investment={investment} key={investment.id} />
        ))}
      </div>
    </>
  );
}Next.js
Fetching Data (Cache)
/codes/react/introduction/invest-app/src/app/page.jsx
import InvestmentCard from '@/components/InvestmentCard';
import Storage from '@/services/supabase';
 
async function getData() {
  return Storage.read('investments');
}
 
export default async function Home() {
  const investments = await getData();
 
  return (
    <>
      <h1 className="text-center text-2xl my-12 font-bold">Investimentos</h1>
 
      <div className="investments grid grid-cols-3 gap-3">
        {investments.map((investment) => (
          <InvestmentCard investment={investment} key={investment.id} />
        ))}
      </div>
    </>
  );
}/codes/react/introduction/invest-app/src/app/page.jsx
import InvestmentCard from '@/components/InvestmentCard';
import Storage from '@/services/supabase';
 
async function getData() {
  return Storage.read('investments');
}
 
export default async function Home() {
  const investments = await getData();
 
  return (
    <>
      <h1 className="text-center text-2xl my-12 font-bold">Investimentos</h1>
 
      <div className="investments grid grid-cols-3 gap-3">
        {investments.map((investment) => (
          <InvestmentCard investment={investment} key={investment.id} />
        ))}
      </div>
    </>
  );
}Routes

Fonte: Next.js Docs - Routing Fundamentals - Route Segments

Fonte: Next.js Docs - Routing Fundamentals - Defining Routes
Dynamic Routes
/codes/react/introduction/invest-app/src/app/[investment]/page.jsx
import { formatCurrency, formatDate } from '@/lib/format';
import Storage from '@/services/supabase';
 
export async function generateStaticParams() {
  const investments = await Storage.read('investments');
 
  return investments.map((investment) => ({
    slug: investment.id,
  }));
}
 
async function getData(slug) {
  const investment = await Storage.read('investments', slug);
 
  return investment;
}
 
export default async function Investment({ params: { slug } }) {
  const [{ name, value, origin, category, interest, created_at }] =
    await getData(slug);
 
  return (
    <>
      <h1 className="text-center text-2xl my-12 font-bold">{name}</h1>
      <div className="w-64 m-auto">
        <p className="text-gray-600 flex justify-between p-1">
          <span className="font-bold mr-1">Valor:</span>
          <span className="investment-origin">{formatCurrency(value)}</span>
        </p>
        <p className="text-gray-600 flex justify-between p-1">
          <span className="font-bold mr-1">Origem:</span>
          <span className="investment-origin">{origin}</span>
        </p>
        <p className="text-gray-600 flex justify-between p-1">
          <span className="font-bold mr-1">Categoria:</span>
          <span className="investment-category">{category}</span>
        </p>
        <p className="text-gray-600 flex justify-between p-1">
          <span className="font-bold mr-1">Taxa:</span>
          <span className="investment-interest">{interest}</span>
        </p>
        <p className="text-gray-600 flex justify-between p-1">
          <span className="font-bold mr-1">Data:</span>
          <span className="investment-created_at">
            {formatDate(created_at)}
          </span>
        </p>
      </div>
    </>
  );
}/codes/react/introduction/invest-app/src/app/[investment]/page.jsx
import { formatCurrency, formatDate } from '@/lib/format';
import Storage from '@/services/supabase';
 
export async function generateStaticParams() {
  const investments = await Storage.read('investments');
 
  return investments.map((investment) => ({
    slug: investment.id,
  }));
}
 
async function getData(slug) {
  const investment = await Storage.read('investments', slug);
 
  return investment;
}
 
export default async function Investment({ params: { slug } }) {
  const [{ name, value, origin, category, interest, created_at }] =
    await getData(slug);
 
  return (
    <>
      <h1 className="text-center text-2xl my-12 font-bold">{name}</h1>
      <div className="w-64 m-auto">
        <p className="text-gray-600 flex justify-between p-1">
          <span className="font-bold mr-1">Valor:</span>
          <span className="investment-origin">{formatCurrency(value)}</span>
        </p>
        <p className="text-gray-600 flex justify-between p-1">
          <span className="font-bold mr-1">Origem:</span>
          <span className="investment-origin">{origin}</span>
        </p>
        <p className="text-gray-600 flex justify-between p-1">
          <span className="font-bold mr-1">Categoria:</span>
          <span className="investment-category">{category}</span>
        </p>
        <p className="text-gray-600 flex justify-between p-1">
          <span className="font-bold mr-1">Taxa:</span>
          <span className="investment-interest">{interest}</span>
        </p>
        <p className="text-gray-600 flex justify-between p-1">
          <span className="font-bold mr-1">Data:</span>
          <span className="investment-created_at">
            {formatDate(created_at)}
          </span>
        </p>
      </div>
    </>
  );
}Linking and Navigating
/codes/react/introduction/invest-app/src/components/InvestmentCard.jsx
import Link from 'next/link';
 
import { IconTrash } from '@tabler/icons-react';
import { formatCurrency, formatDate } from '@/lib/format';
 
export default function InvestmentCard({
  id,
  name,
  value,
  origin,
  category,
  interest,
  created_at,
}) {
  return (
    <div className="bg-white shadow-md rounded-lg p-4 relative">
      <div className="flex justify-between items-center">
        <Link href={`/investments/${id}`}>
          <h3 className="investment-name text-lg font-semibold text-gray-700">
            {name}
          </h3>
        </Link>
        <p className="investment-value text-lg font-semibold text-gray-700">
          {formatCurrency(value / 100)}
        </p>
      </div>
      <div className="mt-4">
        ...
      </div>
    </div>
  );
}/codes/react/introduction/invest-app/src/components/InvestmentCard.jsx
import Link from 'next/link';
 
import { IconTrash } from '@tabler/icons-react';
import { formatCurrency, formatDate } from '@/lib/format';
 
export default function InvestmentCard({
  id,
  name,
  value,
  origin,
  category,
  interest,
  created_at,
}) {
  return (
    <div className="bg-white shadow-md rounded-lg p-4 relative">
      <div className="flex justify-between items-center">
        <Link href={`/investments/${id}`}>
          <h3 className="investment-name text-lg font-semibold text-gray-700">
            {name}
          </h3>
        </Link>
        <p className="investment-value text-lg font-semibold text-gray-700">
          {formatCurrency(value / 100)}
        </p>
      </div>
      <div className="mt-4">
        ...
      </div>
    </div>
  );
}Tratamento de Evento
$ npm install -d @iconify/react$ npm install -d @iconify/react/codes/react/introduction/invest-app/src/components/InvestmentCard.jsx
'use client';
 
import Link from 'next/link';
 
import { IconTrash } from '@tabler/icons-react';
import { formatCurrency, formatDate } from '@/lib/format';
 
export default function InvestmentCard({
  id,
  name,
  value,
  origin,
  category,
  interest,
  created_at,
}) {
  const handleDeleteInvestment = (name) => {
    confirm(`Deseja remover ${name}?`);
  };
 
  return (
    <div className="bg-white shadow-md rounded-lg p-4 relative">
      <div className="flex justify-between items-center">
        <Link href={`/investments/${id}`}>
          <h3 className="investment-name text-lg font-semibold text-gray-700">
            {name}
          </h3>
        </Link>
        <p className="investment-value text-lg font-semibold text-gray-700">
          {formatCurrency(value / 100)}
        </p>
      </div>
      <div className="mt-4">
        ...
      </div>
      <div className="absolute bottom-4 right-4 inline-flex">
        <IconTrash
          size={20}
          className="text-gray-400 hover:text-gray-500 cursor-pointer"
          onClick={() => handleDeleteInvestment(name)}
        />
      </div>
    </div>
  );
}/codes/react/introduction/invest-app/src/components/InvestmentCard.jsx
'use client';
 
import Link from 'next/link';
 
import { IconTrash } from '@tabler/icons-react';
import { formatCurrency, formatDate } from '@/lib/format';
 
export default function InvestmentCard({
  id,
  name,
  value,
  origin,
  category,
  interest,
  created_at,
}) {
  const handleDeleteInvestment = (name) => {
    confirm(`Deseja remover ${name}?`);
  };
 
  return (
    <div className="bg-white shadow-md rounded-lg p-4 relative">
      <div className="flex justify-between items-center">
        <Link href={`/investments/${id}`}>
          <h3 className="investment-name text-lg font-semibold text-gray-700">
            {name}
          </h3>
        </Link>
        <p className="investment-value text-lg font-semibold text-gray-700">
          {formatCurrency(value / 100)}
        </p>
      </div>
      <div className="mt-4">
        ...
      </div>
      <div className="absolute bottom-4 right-4 inline-flex">
        <IconTrash
          size={20}
          className="text-gray-400 hover:text-gray-500 cursor-pointer"
          onClick={() => handleDeleteInvestment(name)}
        />
      </div>
    </div>
  );
}