FamilySearch - Tree Team
import { useLoaderData } from "@remix-run/react";
import { prisma } from "../db";
export async function loader() {
return json(await prisma.user.findMany());
}
export default function Users() {
const data = useLoaderData<typeof loader>();
return (
<ul>
{data.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
export const getServerSideProps = (async () => {
// Fetch data from external API
const res = await fetch('https://api.github.com/repos/vercel/next.js')
const repo = await res.json()
// Pass data to the page via props
return { props: { repo } }
})
export default function Page({ repo }) {
return (
<main>
<p>{repo.stargazers_count}</p>
</main>
)
}
import { prisma } from "../db";
export default async function Users() {
const users = await prisma.user.findMany()
return (
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
Server Component | Client Component | |
---|---|---|
Rendered by Server | Yes | Yes, if passed data |
Rendered By Client | Yes if navigating | Yes |
import { use } from 'react';
import { ThemeContext } from '../theme';
function MessageComponent() {
const theme = use(ThemeContext);
return (
<div className={theme}>
...
</div>
)
}
import { useContext } from 'react';
import { ThemeContext } from '../theme';
function MessageComponent() {
const theme = useContext(ThemeContext);
return (
<div className={theme}>
...
</div>
)
}
import { use, Suspense } from 'react';
import { getUsers } from '../service/users';
function Users({usersPromise}) {
const users = use(usersPromise);
return (
<Suspense fallback='Loading users...'>
<ul>
{users.map(user=>{
return <li>{user.name}</li>
})}
</ul>
</Suspense>
)
}
function App(){
const usersPromise = getUsers()
return (
<div>
<Users usersPromise={usersPromise}/>
</div>
)
}
ref as a prop
import { useRef, forwardRef } from 'react';
const Input = forwardRef(({ label, ...otherProps }, ref) => {
return (
<label>
{label}
<input {...otherProps} ref={ref} />
</label>
);
});
const Form = () => {
const ref = useRef(null);
function handleClick() {
ref.current.focus();
}
return (
<form>
<Input label="Enter your name:" ref={ref} />
<button type="button" onClick={handleClick}>
Edit
</button>
</form>
);
}
import { useRef } from 'react';
const Input = ({ label, ref, ...otherProps }) => {
return (
<label>
{label}
<input {...otherProps} ref={ref} />
</label>
);
};
import { createContext, useState } from 'react'
const ThemeContext = createContext()
export default function ThemeProvider = ({children}) => {
const value = useState('dark')
return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>
}
import { createContext, useState } from 'react'
const ThemeContext = createContext()
export default function ThemeProvider = ({children}) => {
const value = useState('dark')
return <ThemeContext value={value}>{children}</ThemeContext>
}
import React from 'react'
const PedigreePage = ({pedigree}) => {
const name = pedigree[0].name
return (
<div>
<title>{name}</title>
<meta name="description" content={`${name} is cool`}>
<link rel="stylesheet" href="/path/to/styles.css" />
// rendered pedigree
</div>
)
}
the React core team envisions apps to be written
$ npx create-react-app cool-new-app
<html>
<body>
<form action="/page/path" method="POST">
<label id="name">Name:</label>
<input type="text" name="name" />
<button type="submit">Submit</button>
</form>
</body>
</html>
// server.js
app.post('/page/path', (req, res)=>{
const formData = new FormData(req.body)
const name = formData.get('name')
await db.save(name)
res.redirect('/other/path')
})
const Component = () => {
const handleSubmit = async (values)=> {
await axios.post('/api/url', values)
}
return (
<form onSubmit={handleSubmit}>
<label id="name">Name:</label>
<input type="text" name="name" />
<button type="submit">Submit</button>
</form>
)
}
const app = require('express')()
app.post('/api/url', (req, res)=>{
const body = req.body
db.save(body)
res.json({success: true})
})
app.listen(8080)
export default function Page (){
const fetcher = useFetcher()
return (
<fetcher.Form method="POST">
<label id="name">Name:</label>
<input type="text" name="name" />
<button type="submit">Submit</button>
</fetcher.Form>
)
}
export async function action({request}) {
const formData = await request.formData();
const name = formData.get("name");
await db.save(name);
return redirect('/other/page');
}
import { saveActionHandler } from '../actions.js'
const Page = ()=>{
return (
<form action={saveActionHandler}>
<label id="name">Name:</label>
<input type="text" name="name" />
<button type="submit">Submit</button>
</form>
)
}
// actions.js
'use server'
const saveActionHandler = async (formData) => {
const name = formData.get('name')
await db.save(name)
revalidatePath('/other/page')
redirect('/other/page')
}
Server
Client
Microservice
getData()
revalidatePath()
Australia - 3G - Moto G4
These are the features you're looking for.