2.0.24 • Published 1 year ago

@ctsj/state v2.0.24

Weekly downloads
63
License
MIT
Repository
github
Last release
1 year ago

CTSJ-STATE

  • 一个简单的状态集管理(同时实现了 dva 数据流和 logger 中间件)

简介

  • 把 redux、react-redux、redux-logger 和 dva 数据流结合起来的一个简版状态集
  • 本数据集的特点是增加了同步的回调功能和根据 Servive 自动生成 model 和 mapStateToProps、mapDispatchToProps 和 Model 功能

安装

npm install @ctsj/state

目录

状态集本身

createStore 说明:

  • createStore(reducer,preloadedState) + reducer-和 redux 的 reducer 一致 + preloadedState-Store 的初始化值 例子:
import { createStore } from '@ctsj/state/lib/state';

function reducer(state, action) {
  const { data = [] } = state;
  const { type } = action;
  switch (type) {
    case 'add':
      data.push({ id: 1 });
      break;
    default:
      break;
  }
  return state;
}

const store = createStore(reducer, { a: 1, b: 2 });

combineReducers 说明:

  • reducers- Object
  • 例子:
reducer.jsx;

import uuid from 'uuid/v1';

/**
 * addTodo
 * @param {Object} - state
 * @param {Object} - action
 * @return {Array}
 */
export function addTodo(state, action) {
  const { type, value } = action;
  const { data = [] } = state;

  switch (type) {
    case 'add':
      data.push({
        id: uuid(),
        value,
        type: 'run', // completed
      });
      break;
    default:
      break;
  }
  return state;
}

/**
 * updateTodo
 * @param {Object} - state
 * @param {Object} - action
 * @return {Object|Array}
 */
export function updateTodo(state, action) {
  const { data = [] } = state;
  const { id, value, type } = action;
  switch (type) {
    case 'update':
      const index = data.findIndex((t) => t.id === id);
      if (index !== -1) {
        data[index].value = value;
      }
      break;
    default:
      break;
  }
  return state;
}

/**
 * completeTodo
 * @param {Object} - state
 * @param {Object} - action
 * @return {Array}
 */
export function completeTodo(state, action) {
  const { data = [] } = state;
  const { id, type } = action;
  switch (type) {
    case 'complete':
      const index = data.findIndex((t) => t.id === id);
      if (index !== -1) {
        data[index].type = 'complete';
      }
      break;
    default:
      break;
  }
  return state;
}

/**
 * deleteTodo
 * @param {Object} - state
 * @param {Object} - action
 * @return {Object|Array}
 */
export function deleteTodo(state, action) {
  const { data = [] } = state;
  const { id } = action;
  switch (action.type) {
    case 'delete':
      const index = data.findIndex((t) => t.id === id);
      if (index !== -1) {
        data.splice(index, 1);
      }
      break;
    default:
      break;
  }
  return state;
}

index.jsx;

import { createStore, combineReducers } from '@ctsj/state/lib/state';
import { addTodo, updateTodo, completeTodo, deleteTodo } from './reducer';

const reducer = combineReducers({
  addTodo,
  updateTodo,
  completeTodo,
  deleteTodo,
});

const store = createStore(reducer, {
  data: [],
});

Store

  • 方法:
    • getStatus - 返回 state
    • subscribe - 监听 state 的数据变化,返回值是注销监听句柄
    • dispatch - action 发送数据改变

React 中使用

Provider props:

  • store - Store 例子:
import { Provider } from '@ctsj/state/lib/react';
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('app'),
);

connect 说明:

  • mapStateToProps - 处理 state 到 props 的合并
  • mapDispatchToProps - 用 dispatch 处理数据改变
  • React 组件
  • Callback - 渲染完成会后的回调函数 例子:
import React from 'react';
import { connect } from '@ctsj/state/lib/react';
import Immutable from '@ctsj/state/lib/util/immutable';

import './header.less';

const selectorPrefix = 'ctsj-state-todolist';

/**
 * Header
 * @param onAdd
 * @return {*}
 * @constructor
 */
function Header({ onAdd }) {
  return (
    <div className="header">
      <div className="title">ToDoList</div>
      <div className="input">
        <input
          placeholder="&#x6DFB;&#x52A0;ToDo"
          type="text"
          onKeyUp={(e) => {
            const {
              which,
              target: { value },
            } = e;
            if (which === 13) {
              onAdd(value);
            }
          }}
        />
      </div>
    </div>
  );
}

const mapStateToProps = (state) => {
  return Immutable.cloneDeep(state);
};

const mapDispatchToProps = (dispatch) => {
  return {
    onAdd: (value) => {
      dispatch({
        type: 'add',
        value,
      });
    },
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(Header);

中间件

  • logger 中间件
import { createStore, applyMiddleware } from '@ctsj/state/lib/state';
import { createLoggerMiddleware } from '@ctsj/state/lib/middleware';

const store = createStore(null, {}, applyMiddleware(createLoggerMiddleware()));
  • saga 中间件和 dva 用法一致
    • 引入
import { createStore, applyMiddleware } from '@ctsj/state/lib/state';
import { createSagaMiddleware } from '@ctsj/state/lib/middleware';

const store = createStore(null, {}, applyMiddleware(createSagaMiddleware()));
  • Model
export default {
	namespace: 'todolist',
	state:{
		data: [],
	},
	effects: {
		*fetchList(params.{call,all,put,select}){
			...
		}
	},
	reducers: {
		receive(state, { payload }) {
			return {
				...state,
				...payload,
			};
		},
	},
}

用 Service 自动生成 mapStateToProps、mapDispatchToProps 和 Model

使用 state 作为数据源

有的时候使用者其实想使用 model 的整体处理数据的能力,但组件间又没有共享数据的交换,这个是后就可以把数据源设置成 state,现在就可以实现使用 state 作为数据源,同时也能使用 model 处理数据的能力。

  • 使用 class 的方式 使用 createState 方法对 state 进行包装即可
import ServiceRegister from '@ctsj/state/lib/middleware/saga/serviceregister';
import createState from '@ctsj/state/lib/react/createState';

class UserList extends React.Component {
  constructor(props) {
    super(props);

    // 初始化的state数据
    this.state = {

    }

    const models = [];
    const requireComponent = require.context('../../../../model', false, /.*\.(js)$/);
    requireComponent.keys().forEach((fileName) => {
      const model = requireComponent(fileName);
      models.push(model.default());
    });

    // 使用createState对state进行包装
    this.unsubscribe = createState({
      initialState: Object.assign({}, this.state),
      models,
      mapState: (state) =>
        Object.assign(
          ServiceRegister.mapStateToProps({
            namespaces: [serviceName],
            state,
          }),
          {
            loading: state.loading,
          },
        ),
      mapDispatch: (dispatch) =>
        ServiceRegister.mapDispatchToProps({
          namespaces: [serviceName],
          dispatch,
        }),
      ref: this,
      middleWares: [],
      reducer: null,
    });
  }

  componentWillUnmount() {
    // 销毁的时候注销
    this.unsubscribe();
  }

  ......

}
  • 使用 hooks 的方式
import { useSagaState } from '@ctsj/state/lib/react';
import ServiceRegister from '@ctsj/state/lib/middleware/saga/serviceregister';

export default () => {
  useEffect(() => {
    // 加载数据
  }, []);

  const models = [];
  const requireComponent = require.context('../../../../model', false, /.*\.(js)$/);
  requireComponent.keys().forEach((fileName) => {
    const model = requireComponent(fileName);
    models.push(model.default());
  });

  // 使用useSagaState对state进行包装
  const state = useSagaState({
    initialState: {},
    models,
    mapState: (state) =>
      Object.assign(
        ServiceRegister.mapStateToProps({
          namespaces: [serviceName],
          state,
        }),
        {
          loading: state.loading,
        },
      ),
    mapDispatch: (dispatch) =>
      ServiceRegister.mapDispatchToProps({
        namespaces: [serviceName],
        dispatch,
      }),
    middleWares: [],
    reducer: null,
  });
  
  ......

};

ToDoList

进入 demo 目录

  1. npm install
  2. npm run startapp
  3. 浏览器输入 localhost:8000
2.0.24

1 year ago

2.0.22

2 years ago

2.0.23

2 years ago

2.0.21

3 years ago

2.0.20

3 years ago

2.0.19

3 years ago

2.0.18

3 years ago

2.0.17

3 years ago

2.0.16

3 years ago

2.0.15

3 years ago

2.0.14

3 years ago

2.0.13

3 years ago

2.0.12

3 years ago

2.0.11

3 years ago

2.0.10

3 years ago

2.0.9

4 years ago

2.0.7

4 years ago

2.0.8

4 years ago

2.0.6

4 years ago

2.0.5

4 years ago

2.0.3

4 years ago

2.0.4

4 years ago

2.0.2

4 years ago

2.0.1

4 years ago

1.0.7

4 years ago

1.0.6

4 years ago

1.0.5

4 years ago

1.0.4

4 years ago

1.0.2

4 years ago

1.0.3

4 years ago

1.0.1

4 years ago

1.0.0

5 years ago