1.2.12-alpha.0 • Published 4 years ago

@alekna/react-store v1.2.12-alpha.0

Weekly downloads
-
License
MIT
Repository
github
Last release
4 years ago

size gzip size

Usage

Example

useAsyncReducer

Try it out in the browser

Works just like react useReducer, but dispatcher can also handle promises and observables

import React from 'react';
import { render } from 'react-dom';
import { interval } from 'rxjs';
import { map, take, startWith } from 'rxjs/operators';
import { useAsyncReducer } from '@alekna/react-store';

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

function reducer(state = { count: 0 }, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      return state;
  }
}

const App = () => {
  const [state, dispatch] = useAsyncReducer(reducer);
  return (
    <>
      <div>Count: {state.count}</div>
      <div>
        <button
          style={{ padding: '10px 20px', fontSize: 24 }}
          onClick={() =>
            dispatch(async () => {
              await sleep(500);
              return { type: 'increment' };
            })
          }
        >
          +
        </button>
        <button
          style={{ padding: '10px 20px', fontSize: 24 }}
          onClick={() => dispatch({ type: 'decrement' })}
        >
          -
        </button>
        <button
          style={{ padding: '10px 20px', fontSize: 24 }}
          onClick={() =>
            dispatch(() => {
              return interval(1000).pipe(
                startWith(0),
                take(5),
                map(() => ({
                  type: 'increment',
                })),
              );
            })
          }
        >
          auto click
        </button>
      </div>
    </>
  );
};

render(<App />, document.getElementById('root'));

Usage with hooks api

Try it out in the browser

import React from 'react';
import { render } from 'react-dom';
import { of } from 'rxjs';
import { delay } from 'rxjs/operators';
import { useStore, createStore } from '@alekna/react-store';

const onChange = text => () => {
  return of({
    type: 'onChange',
    payload: text,
  }).pipe(delay(1000));
};

function reducer(state = { text: '' }, action) {
  switch (action.type) {
    case 'onChange':
      return {
        ...state,
        text: state.text.concat(action.payload.slice(-1)),
      };
    default:
      return state;
  }
}
const storeConfig = createStore(reducer);

function App() {
  const { state, dispatch } = useStore(storeConfig);

  return (
    <div style={{ display: 'flex', flexDirection: 'column' }}>
      <h1>Start typing bellow</h1>
      <input
        value={state.text}
        placeholder="your input will be delayed by 1sec"
        onChange={evt => dispatch(onChange(evt.target.value))}
      />
    </div>
  );
}

render(<App />, document.getElementById('root'));

Usage with render props and context api

Try it out in the browser

import React from 'react';
import { render } from 'react-dom';
import { of } from 'rxjs';
import { delay } from 'rxjs/operators';
import StoreProvider, { createStore, useSelector } from '@alekna/react-store';

const onChange = text => () => {
  return of({
    type: 'onChange',
    payload: text,
  }).pipe(delay(1000));
};

function reducer(state = { text: '' }, action) {
  switch (action.type) {
    case 'onChange':
      return {
        ...state,
        text: state.text.concat(action.payload.slice(-1)),
      };
    default:
      return state;
  }
}
const storeConfig = createStore(reducer);

function App() {
  return (
    <StoreProvider store={storeConfig}>
      {({ dispatch }) => (
        <div style={{ display: 'flex', flexDirection: 'column' }}>
          <h1>Start typing bellow</h1>
          <Input dispatch={dispatch} />
        </div>
      )}
    </StoreProvider>
  );
}

function Input({ dispatch }) {
  const text = useSelector(state => state.text);
  return (
    <input
      value={text}
      placeholder="your input will be delayed by 1sec"
      onChange={evt => dispatch(onChange(evt.target.value))}
    />
  );
}

render(<App />, document.getElementById('root'));