殷勤昨夜三更雨,又得浮生一日凉。——《鹧鸪天》苏轼javascript
实践之结果发布于github,地址:react-duce前端
不知从什么时候起,状态管理成了一个前端项目的标配,不论有无须要,咱们都会引入诸如MobX、Redux库来管理咱们应用的状态。但若是咱们回头想一想以前项目中的某些架构,难免感叹,为什么个人项目功能间设计耦合如此之紧,为何这部分根本不须要抽离的公共状态却抽离了,又为什么组件的状态和UI耦合?java
自react发布之初就使用react的同窗想必能感叹react发展历程中的每一步都走得稳健,从mixin到class component到function component;从pureComponent到memo,无不是在追求更好的性能与更优的程序范式。实不相瞒,自react 16.8发布hooks,我便爱react更多几分,于此对组件之间状态的管理有了更进一步的思考,完毕,凝结出了这个库react-duce
,但愿与你们共同探讨hooks在项目中的实践。react
前段时间,看到一个通讯库,swr,基于hook的数据请求库,其设计原理很容易理解,当获得返回的请求数据时,调用状态处理函数,更新状态,进而在使用该状态的组件中获得数据更新。源码片断以下:git
import useSWR from 'swr' function Profile () { const { data, error } = useSWR('/api/user', fetcher) if (error) return <div>failed to load</div> if (!data) return <div>loading...</div> return <div>hello {data.name}!</div> } 复制代码
hook不只使代码可读性更高,并且可以使模块间耦合下降。github
部分代码片断实例以下:redux
import React from 'react'; import { createStore, useStore } from 'react-duce'; // 建立公共store createStore('countStore', 0); const HelloContent = () => { // 使用公共store const [ count, setCount ] = useStore('countStore'); return ( <span onClick={() => setCount(count + 1)}>{count}</span> ) } const WorldContent = () => { // 使用公共store const [ count ] = useStore('countStore'); return ( <span>{count}</span> ) }复制代码
在HelloContent组件中点击span,便可触发count更新,进而WorldContent中的count也获得更新,实现组件之间store共享。
api
曾几什么时候,咱们感叹flux,感叹redux使咱们对于状态的管理更加清晰,使咱们对数据的流向成竹在胸。markdown
使用实例以下:
架构
import React from 'react'; import { createStore, useStore } from 'react-duce'; // 定义reducer const reducer = (state, action) => { // you must return a new state value when a reducer is being used. switch (action.type) { case 'add': const id = state.length; return [ ...state, { id, text: action.payload } ]; case 'delete': return state.filter(todo => todo.id !== action.payload) default: return state; } } // 建立指定reducer的store const todoStore = createStore( 'todoStore', [ {id: 0, text: 'Sing'} ], reducer ); function AddTodo() { // 返回状态及dispatch函数 const [state, dispatch] = useStore('todoStore'); const inputRef = React.useRef(null); const onSubmit = e => { e.preventDefault(); const todo = inputRef.current.value; inputRef.current.value = ''; // 触发状态更新 dispatch({ type: 'add', payload: todo }); }; return ( <form onSubmit={onSubmit}> <input ref={inputRef} /> <button>Create</button> </form> ); } function TodoList() { const [todos, dispatch] = useStore(todoStore); const deleteTodo = id => dispatch({ type: 'delete', payload: id }); return ( <ul> <h2>todolist</h2> {todos.map(todo => ( <li key={todo.id}> {todo.text} <button onClick={() => deleteTodo(todo.id)} type="button"> X </button> </li> ))} </ul> ); } export { TodoList, AddTodo };复制代码
Store基类
class Store { name; state; reducer; dispatchers; dispatch; subscribe(callback) {}; dispatch(action, callback) {}; }复制代码
建立store
export function createStore(name, state = {}, reducer) { const store = new Store(name, state, reducer); ?stores = Object.assign({}, ?stores, {[name]: store}) }复制代码
使用store
export function useStore(identifier) { const store = getStoreItem(identifier); // 使用useState建立状态与处理函数 const [state, set] = useState(store.state); useEffect(() => { // ... }, []) return [state, store.dispatch]; }复制代码
当状态函数执行时,状态更新并遍历该状态全部set函数。