Skip to main content

React

Getting started​

Let's create a little app to demonstrate how to use React in flecks:

npm init @flecks/app react-test
cd react-test

We'll also create a little fleck to hold our root component:

npm init @flecks/fleck -w packages/root

We'll add the react fleck to our new fleck:

cd packages/root
npx flecks add @flecks/react
tip

We add @flecks/react to packages/root instead of our application directory so that our new fleck encapsulates all the dependencies it needs. You can distribute your flecks to others if you do this right!

Add a root component​

Let's implement a hook to add a component to @flecks/react's root components:

packages/root/src/index.js
import Component from './component';

export const hooks = {
'@flecks/react.roots': () => Component,
};

Let's also add our component source file:

packages/root/src/component.jsx
import {React} from '@flecks/react';

function Component() {
return <p>hello world (from React)</p>;
}

export default Component;
Hey, where's my React?

You may notice we imported React from @flecks/react instead of react. This is provided as a convenience. flecks is a very dynamic system and it may also be possible to load multiple React versions on your page.

Using @flecks/react makes sure your components are all using the same instance of React.

Go check it out​

Start your application:

npm run start

Visit your website in your browser and you will see the hello world message!

Server-Side Rendering (SSR)

If you disable JavaScript in your browser and reload the page you will still see the message. This is because Server-Side Rendering (SSR) is enabled by default! If you don't want this, update your build/flecks.yml:

build/flecks.yml
'@flecks/core':
id: react-test
'@flecks/react':
ssr: false
'@flecks/server': {}
'@react-test/root:./packages/root/src': {}

Now if you visit the page with JavaScript disabled, you will get a white page.

Hot module reloading​

You'll notice that if you edit your component, the changes are immediately reflected on the page. This is because we have HMR support in our application!

Routing​

flecks provides @flecks/react/router which implements server and client routing using React Router's <RouterProvider>.

Just add it to flecks.yml:

build/flecks.yml
'@flecks/core':
id: react-test
'@flecks/react': {}
'@flecks/react/router': {}
'@flecks/server': {}
'@react-test/root:./packages/root/src': {}

Filetree routing​

It is possible to define your routes as a file structure. A helper is provided to build a routes object from your file structure:

import {createRoutesFromContext} from '@flecks/react/router';

export const hooks = {
'@flecks/react/router.routes': () => (
createRoutesFromContext(require.context('./routes'))
),
};

Supposing your ./routes directory was structured as:

routes
├─ index.jsx
├─ [...catchall].jsx
├─ -optional.jsx
├─ -[optionalDynamic].jsx
├─ about.jsx
└─ team/
└─ [teamId]/
├─ index.jsx
└─ edit.jsx

Your routes object would look like:

[
{path: '/', ...},
{path: '*', ...},
{path: '/about', ...},
{path: '/optional?', ...},
{path: '/:optionalDynamic?', ...},
{
path: '/team', ...,
children: [
{
path: ':teamId', ...
},
{
path: ':teamId/edit', ...
},
],
},
]

Each route object has a ... in the diagram above because each module is import()ed and the exports are mixed in to the Route. Route modules should probably at least export function Component() { ... }, but may export any of the Route props.

You may export a default export which will be used as the component. An explicit named Component export will take precedence.

Selecting the root​

There can only be one root of your router tree. Supposing you implemented @flecks/react/router.routes in your fleck called @my/routes-root, you would set the following configuration in build/flecks.yml to use your fleck's routes as the root:

'@flecks/react/router':
root: '@my/routes-root'

Hooks​

useFlecks()​

You may use this hook from your components to gain access to the flecks instance.

Example:

function Component() {
const flecks = useFlecks();
const id = flecks.get('@flecks/core.id');
return <p>Your application ID is {id}</p>;
}

useEvent(object, eventName, fn)​

object​

The event emitter to listen to

eventName​

The name of the event to listen for.

fn​

The event handler to call.

Example:

function Component() {
const flecks = useFlecks();
const [isConnected, setIsConnected] = useState(false);
useEvent(flecks.socket, 'connect', () => {
setIsConnected(true);
});
useEvent(flecks.socket, 'disconnect', () => {
setIsConnected(false);
});
return <p>Socket is {isConnected ? 'connected' : 'disconnected'}.</p>;
}

usePrevious(value)​

value​

The value whose previous value we're interested in.

See: https://blog.logrocket.com/accessing-previous-props-state-react-hooks/