docs/pages/packages/client.mdx 4.9 K raw
1
import { Button } from 'vocs/components'
2
3
# `client`
4
5
bhvr uses Vite + React as its default client side template, as React has become one of the industry defaults with a vast amount of ecosystem support. With that said you can absolutely replace it with your client of choice by [following the guide](). We highly recommend using [Vite](https://vite.dev) as your bundler since it too has lots of ecosystem suppport and is very lightweight.
6
7
8
## Basics
9
10
Just in case you haven't used Vite + React much here are some basics you may want to keep in mind.
11
12
### Client Side Only
13
14
Unlike Next.js, Vite + React is client side only. This means any kind of environment variable used here will be publicly accessible, which is why we have a [`server`](/packages/server) package to keep those secure. This can take some getting used to when building an application and how you might fetch data. A classic way to achieve an "on-load" API call to your server is through a `useEffect`.
15
16
```tsx App.tsx
17
import { useState, useEffect } from 'react';
18
19
function UserProfile() {
20
  const [user, setUser] = useState(null);
21
  const [loading, setLoading] = useState(true);
22
  const [error, setError] = useState(null);
23
24
  useEffect(() => {
25
    // Define an async function inside useEffect
26
    async function fetchUser() {
27
      try {
28
        setLoading(true);
29
        // Make the API call to your server
30
        const response = await fetch(`${import.meta.env.SERVER_URL}`);
31
32
        // Handle non-200 responses
33
        if (!response.ok) {
34
          throw new Error(`Error: ${response.status}`);
35
        }
36
37
        const data = await response.json();
38
        setUser(data);
39
        setError(null);
40
      } catch (err) {
41
        setError(err.message);
42
        setUser(null);
43
      } finally {
44
        setLoading(false);
45
      }
46
    }
47
48
    // Call the function
49
    fetchUser();
50
51
    // If needed, you can return a cleanup function
52
    return () => {
53
      // Any cleanup code (if needed)
54
    };
55
  }, []); // Empty dependency array means this runs once on mount
56
57
  if (loading) return <div>Loading...</div>;
58
  if (error) return <div>Error: {error}</div>;
59
  if (!user) return <div>No user data found</div>;
60
61
  return (
62
    <div>
63
      <h2>User Profile</h2>
64
      <p>Name: {user.name}</p>
65
      <p>Email: {user.email}</p>
66
    </div>
67
  );
68
}
69
```
70
71
### Environment Variables
72
73
Despite environment variables being public in this setup, they still come in handy for things like working with your local server URL vs your deployed instance. It's best practice to keep your variables in a `.env.local` file with the following format, taking special note that they need to start with `VITE_`.
74
75
```
76
// [!code word:VITE]
77
VITE_MY_VAR=value
78
```
79
80
To use them inside your app be sure to use this Vite formatting
81
82
```typescript
83
const variable = import.meta.env.VITE_MY_VAR
84
```
85
86
### Check the Config
87
88
Vite's config file `vite.config.ts` is worth exploring as it can provide some extra options and plugins.
89
90
## Styles
91
92
When creating a new bhvr project you can use the CLI to specify the CSS template you want
93
94
```bash [terminal]
95
bun create bhvr@latest --template default # Classic CSS
96
bun create bhvr@latest --template tailwind # Tailwind installed and setup
97
bun create bhvr@latest --template shadcn # Tailwind + Shadcn/ui component setup
98
```
99
100
## Routing
101
102
There are serveral ways to handle routing in your client app, but few come close to [React Router](http://reactrouter.com). Setting it up is quite simple and intuitive.
103
104
::::steps
105
106
### Install `react-router`
107
108
Make sure you're inside the `client` directory and then install `react-router`
109
110
```bash [terminal]
111
bun add react-router
112
```
113
114
### Setup Router
115
116
You can do this inside `main.tsx` or `App.tsx`, I prefer the latter. All you have to do is import the `BrowserRouter`, `Routes`, then declare your routes with the components they go to inside.
117
118
```tsx App.tsx
119
import { BrowserRouter, Routes, Route } from "react-router";
120
import Home from "./components/Home";
121
122
function App() {
123
  return (
124
    <BrowserRouter>
125
      <Routes>
126
        <Route path="/" element={<Home />} />
127
      </Routes>
128
    </BrowserRouter>
129
  );
130
}
131
132
export default App
133
```
134
135
### Use Dynamic Routes
136
137
If you want to have a dynamic route with a path param you can set it up in your `Routes` like so
138
139
```tsx
140
import { BrowserRouter, Routes, Route } from "react-router";
141
import Home from "./components/Home";
142
import Post from "./components/Post";
143
144
function App() {
145
  return (
146
    <BrowserRouter>
147
      <Routes>
148
        <Route path="/" element={<Home />} />
149
        <Route path="/post/:slug" element={<Post />} />
150
      </Routes>
151
    </BrowserRouter>
152
  );
153
}
154
155
export default App
156
```
157
158
Then inside the component you can access those params with `useParams`
159
160
```typescript
161
import { useParams } from "react-router";
162
163
function Post(){
164
  const { slug } = useParams()
165
166
  return (
167
    <>
168
      <h1>Post {slug}</h1>
169
    </>
170
  )
171
}
172
173
export default Post;
174
```
175
176
::::
177
178
## Deployment
179
180
<Button href="/deployment/client/orbiter">Deployments Section</Button>