Skip to content

nanxiaobei/retalk

Folders and files

NameName
Last commit message
Last commit date
Jan 1, 2023
Jan 1, 2023
Jan 1, 2023
Jan 1, 2023
Jan 1, 2023
May 12, 2020
Jan 1, 2023
May 12, 2020
Apr 10, 2024
Apr 10, 2024
Nov 25, 2019
Jan 1, 2023
Sep 27, 2024
Jan 1, 2023
Jan 1, 2023
Jan 1, 2023

Repository files navigation

Link in bio to widgets, your online home screen. ➫ 🔗 kee.so


Retalk

The Simplest Redux

Travis npm version npm bundle size npm downloads license

English · 简体中文


Features

  • Simplest - Same syntax as a class component
  • Only 2 API - setStore() and withStore()
  • Async model - Code splitting support for models
  • Auto loading - Auto loading state for async actions

Install

yarn add retalk

# npm i retalk

Usage

Model syntax is like a React class component, just without lifecycle methods.

import { Provider, setStore, withStore } from 'retalk';

// Setup model
class CounterModel {
  state = {
    count: 0,
  };
  add() {
    const { count } = this.state; // get own state
    this.setState({ count: ++count }); // set own state
    this.addAsync(); // run own action

    // this.models.someModel.state        -> get another model's state
    // this.models.someModel.someAction() -> run another model's action
  }
  async addAsync() {
    await new Promise((resolve) => setTimeout(resolve, 1000));
    const { count } = this.state;
    this.setState({ count: ++count });
  }
}

// Use in components
const Counter = withStore({
  counter: ['count', 'add', 'addAsync'],
})((props) => {
  const { count, add, addAsync } = props; // addAsync.loading can be use

  return (
    <div>
      <p>{count}</p>
      <button onClick={add}>+</button>
      <button onClick={addAsync}>+ ⏳{addAsync.loading && '...'}</button>
    </div>
  );
});

// Setup store
const store = setStore({ counter: CounterModel });

const App = () => (
  <Provider store={store}>
    <Counter />
  </Provider>
);

Demo

Edit retalk

API

1. setStore()

setStore(models, middleware)

const store = setStore(
  {
    home: HomeModel,
    counter: CounterModel,
  },
  [logger, crashReporter]
);

Pass models and middleware(both are optional), Set up the one and only store.

In development mode, Redux DevTools will be enabled by default, make sure its version >= v2.15.3 and not v2.16.0.

2. withStore()

withStore(...modelNames)(Component)

Eject state and actions of one or more models, to the props of a component. 3 ways to use it:

// 1. Use string to eject all
const Wrapper = withStore('home', 'counter')(Counter);

// The simplest way, but unused props will also trigger re-render.
// Use this if all injected props will be used, or to rapid develop.
// 2. Use object to customize
const Wrapper = withStore({
  home: ['name', 'setName'],
  counter: ['count', 'add', 'addAsync'],
})(Counter);

// Customize the injected props, only inject the needed props.
// 3. Use `mapStateToProps()`... to customize more
const Wrapper = withStore(mapStateToProps, mapDispatchToProps)(Counter);

// For more customization of the injected props,
// use `mapStateToProps`, `mapDispatchToProps` etc.
// react-redux.js.org/api/connect

3. Provider & batch()

Just redux-redux's Provider and batch().

You can import them from retalk to simplify development.

FAQ

Async import models?

Setup the store with setStore(), then use libs like loadable-components to import components and models.

Then, use store.add() to eject models to store.

Here is an example with loadable-components:

import React from 'react';
import loadable from 'loadable-components';

const Wrapper = loadable(async () => {
  const [{ default: Counter }, { default: CounterModel }] = await Promise.all([
    import('./Counter/index.jsx'),
    import('./Counter/Model.js'),
  ]);
  store.add({ counter: CounterModel }); // use `store.add(models)` just like `setStore(models)`
  return (props) => <Counter {...props} />;
});

License

MIT © nanxiaobei