Quickstart

This example will quickly connect your react application to a Trixta space using this package in conjunction with trixta-js-core

Setup CRA Template

yarn create react-app --template cra-template-rb my-example-app
cd my-example-app

Install trixta-js packages

yarn add @trixtateam/trixta-js-core @trixtateam/trixta-js-rjsf @trixtateam/phoenix-to-redux @rjsf/core @rjsf/utils @rjsf/validator-ajv6
Generate Login Page Example
yarn generate

Follow the prompt instructions and create component under Pages directory

Replace file contents with below code. src\app\pages\LoginPage

/**
 *
 * LoginPage
 *
 */
import {
  ReservedTrixtaRoles
} from '@trixtateam/trixta-js-core';
import {
  TrixtaActionComponent,
  TrixtaLoginWidget,
  TrixtaReactionComponent,
} from '@trixtateam/trixta-js-rjsf';
import { PageWrapper } from '../../components/PageWrapper';

interface Props {}

export function LoginPage(props: Props) {
  return (
    <PageWrapper>
    <div
        style={{
          margin: '10px',
          padding: '10px',
          backgroundColor: '#dce6ea',
        }}
      >
        <TrixtaLoginWidget />
      </div>
      <div
        style={{
          margin: '10px',
          padding: '10px',
        }}
      >
        <TrixtaActionComponent
          actionName="example"
          roleName={ReservedTrixtaRoles.EVERYONE_AUTHED}
        />
      </div>
      <div
        style={{
          margin: '10px',
          padding: '10px',
        }}
      >
        <TrixtaReactionComponent
          reactionName="welcome"
          requestForEffect
          roleName={ReservedTrixtaRoles.EVERYONE_AUTHED}
        />
      </div>
    </PageWrapper>
  );
}
Setup Reducer

Replace file contents with below code.

src\store\reducers.ts

/**
 * Combine all reducers in this file and export the combined reducers.
 */

import { combineReducers } from '@reduxjs/toolkit';
import { phoenixReducer } from '@trixtateam/phoenix-to-redux';
import { trixtaReducer } from '@trixtateam/trixta-js-core';
import { InjectedReducersType } from 'utils/types/injector-typings';

/**
 * Merges the main reducer with the router state and dynamically injected reducers
 */
export function createReducer(injectedReducers: InjectedReducersType = {}) {
  // Initially we don't have any injectedReducers, so returning identity function to avoid the error
  if (Object.keys(injectedReducers).length === 0) {
    return state => state;
  } else {
    return combineReducers({
      trixta: trixtaReducer,
      phoenix: phoenixReducer,
      ...injectedReducers,
    });
  }
}
Setup Trixta Saga

Create and copy saga file src\app\sagas\app.ts

import { setupTrixtaSaga } from '@trixtateam/trixta-js-core';
import { fork } from 'redux-saga/effects';

export default function* rootSaga() {
  yield fork(setupTrixtaSaga);
}
Configure Store

Replace file contents with below code.

src\store\configureStore.ts

import {
  configureStore,
  getDefaultMiddleware,
  StoreEnhancer,
} from '@reduxjs/toolkit';
import { createInjectorsEnhancer } from 'redux-injectors';

import { createPhoenixChannelMiddleware } from '@trixtateam/phoenix-to-redux';
import createSagaMiddleware from 'redux-saga';
import { createReducer } from './reducers';

export function configureAppStore() {
  const reduxSagaMonitorOptions = {};
  // Makes redux connected to phoenix channels
  const phoenixChannelMiddleWare = createPhoenixChannelMiddleware();
  const sagaMiddleware = createSagaMiddleware(reduxSagaMonitorOptions);
  const { run: runSaga } = sagaMiddleware;

  // Create the store with saga middleware
  const middlewares = [sagaMiddleware, phoenixChannelMiddleWare];

  const enhancers = [
    createInjectorsEnhancer({
      createReducer,
      runSaga,
    }),
  ] as StoreEnhancer[];

  const store = configureStore({
    reducer: createReducer(),
    middleware: [
      ...getDefaultMiddleware({
        thunk: false,
        immutableCheck: {
          ignore: ['socket', 'channel', 'trixta', 'phoenix', 'router'],
        },
        serializableCheck: false,
      }),
      ...middlewares,
    ],
    devTools:
      /* istanbul ignore next line */
      process.env.NODE_ENV !== 'production' ||
      process.env.PUBLIC_URL.length > 0,
    enhancers,
  });

  return store;
}
Connect Trixta

Replace file contents with below code.

src\app\index.tsx

/**
 *
 * App
 *
 * This component is the skeleton around the actual pages, and should only
 * contain code that should be seen on all pages. (e.g. navigation bar)
 */

import { Helmet } from 'react-helmet-async';
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import { GlobalStyle } from '../styles/global-styles';
import { useTrixtaSpace } from '@trixtateam/trixta-js-core';
import { useTranslation } from 'react-i18next';
import { SagaInjectionModes, useInjectSaga } from 'redux-injectors';
import { HomePage } from './pages/HomePage/Loadable';
import { LoginPage } from './pages/LoginPage';
import { NotFoundPage } from './pages/NotFoundPage/Loadable';
import saga from './sagas/app';
export function App() {
  useInjectSaga({ key: 'App', saga, mode: SagaInjectionModes.DAEMON });
  useTrixtaSpace({ space: 'trixta-demo.space.trixta.io', params: {} });
  const { i18n } = useTranslation();
  return (
    <BrowserRouter>
      <Helmet
        titleTemplate="%s - React Boilerplate"
        defaultTitle="React Boilerplate"
        htmlAttributes={{ lang: i18n.language }}
      >
        <meta name="description" content="A React Boilerplate application" />
      </Helmet>

      <Routes>
        <Route path={process.env.PUBLIC_URL + '/'} element={<HomePage />} />
        <Route
          path={process.env.PUBLIC_URL + '/login'}
          element={<LoginPage />}
        />
        <Route element={<NotFoundPage />} />
      </Routes>
      <GlobalStyle />
    </BrowserRouter>
  );
}

Run Example

yarn start

Last updated