殷勤昨夜三更雨,又得浮生一日涼。——《鷓鴣天》蘇軾
實踐之結果發佈於github,地址:react-duce前端
不知從什麼時候起,狀態管理成了一個前端項目的標配,不論有無須要,咱們都會引入諸如MobX、Redux庫來管理咱們應用的狀態。但若是咱們回頭想一想以前項目中的某些架構,難免感嘆,爲什麼個人項目功能間設計耦合如此之緊,爲何這部分根本不須要抽離的公共狀態卻抽離了,又爲什麼組件的狀態和UI耦合?react
自react發佈之初就使用react的同窗想必能感嘆react發展歷程中的每一步都走得穩健,從mixin到class component到function component;從pureComponent到memo,無不是在追求更好的性能與更優的程序範式。實不相瞞,自react 16.8發佈hooks,我便愛react更多幾分,於此對組件之間狀態的管理有了更進一步的思考,完畢,凝結出了這個庫react-duce
,但願與你們共同探討hooks在項目中的實踐。git
前段時間,看到一個通訊庫,swr,基於hook的數據請求庫,其設計原理很容易理解,當獲得返回的請求數據時,調用狀態處理函數,更新狀態,進而在使用該狀態的組件中獲得數據更新。源碼片斷以下:github
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不只使代碼可讀性更高,並且可以使模塊間耦合下降。typescript
部分代碼片斷實例以下: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使咱們對於狀態的管理更加清晰,使咱們對數據的流向成竹在胸。架構
使用實例以下:ide
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函數。