Getting started

2 minutes read

Applies to 1.1.x
State DRAFT

The following 6 steps are the basics needed to have a working example (source code available in "example/howto/getstarted" folder of source code repository)

1. Install the library as dependency in your React project

npm i -d @hypereact/state

2. Design your Redux store and implement the state interfaces that define each slice of the root state and related initial states

state.ts
// the state slice names as enum elements 
export enum Slices {
  Example = 'example',
  Persisted = 'persistent'
}

//  the example state will just provide slice
export interface ExampleState {
  message: string; // will store a message to be shown
}
// the persistent state will be made persistent against the reload of application
export interface PersistedState {
  count: number; // will store an incrementable count
}

// root state interface representation of slices
export interface RootState {
  example: ExampleState,
  persistent: PersistedState
}

// object for initialization of redux state slices
export const initialExampleState: ExampleState = {
  message: '...'
}
export const initialPersistedState: PersistedState = {
  count: 0
}

3. Create the configuration object that defines Redux slices with related reducers and initialize the store for usual purposes

index.tsx
import {
  IReduxConfig,
  ReduceableReducer,
  PersistentReduceableReducer,
} from "@hypereact/state";

export const reduxConfig: IReduxConfig = {
  example: new ReduceableReducer(initialExampleState),
  persistent: new PersistentReduceableReducer(initialPersistedState)
}

// initialize the singleton instance of StoreManager passing the configuration
// thus you can always get it in your code through StoreManager.getInstance() static function
const storeManager = StoreManager.getInstance(reduxConfig);

// render Provider with store prop as usual
ReactDOM.render(
  <Provider store={StoreManager.getInstance().getStore()}>
  <App />
  </Provider>,
  document.getElementById("root")
);

4. Implement actions (reduce-able in the example) to be dispatched

action.ts
@ReduxAction("SET_EXAMPLE_MESSAGE", Slices.Example)
export class SetExampleMessageAction implements IReduceableAction<ExampleState> {
  constructor(public name: string) {}
  
  reduce(state: ExampleState) {
    state.message = `Hello ${this.name}`;
    return state;
  }
}

@ReduxAction("INCREMENT_PERSISTENT_COUNT", Slices.Persisted)
export class IncrementCountAction implements IReduceableAction<PersistedState> {
  constructor(public incrementBy: number = 1) {}

  reduce(state: PersistedState) {
    state.count += this.incrementBy;
    return state;
  }
}

5. Implement "connected" component and dispatch actions

app.tsx
interface AppProps {
  example?: ExampleState;
  persistent?: PersistedState;
}

// decorate with the React Redux mapStateToProps function as argument
@ReduxConnect((state: RootState) => {
  return {
    ...state,
  };
})
export class App extends React.Component<AppProps> {

  private handleGreet() {
    // dispatch actions
    const storeManager = StoreManager.getInstance();
    storeManager.dispatch(new SetExampleMessageAction("John"));
    storeManager.dispatch(new IncrementCountAction());
  }  

  render() {
    // use props bound to state slices
    const count = this.props.persistent!.count;
    const message = this.props.example!.message;
    return (
      <>
        <div>Clicked {count} with lastest greeting message "{message}".</div>
        <button onClick={this.handleGreet}>Greet</button>
      </>
    );
  }
}

6. reload application to verify persistent state through managed reducer