@equinor/fusion-observable
TypeScript icon, indicating that this package has built-in type declarations

8.4.3 • Public • Published

Observable

React

Observable

type TodoItem = {
  id: string;
  txt: string;
}

type State = Record<string, TodoItem>;

enum ActionType {
  ADD = 'add',
  REMOVE = 'remove'
}

type ActionAdd = {
  type: ActionType.ADD,
  payload: Omit<TodoItem, 'id'>;
}

type ActionRemove = {
  type: ActionType.REMOVE
  payload: string;
}

type Actions = ActionAdd | ActionRemove

const reducer = (state: State, action: Actions) => {
  switch(action) {
    case ActionType.ADD:
      return {
        ...state,
        [generateId()]: action.payload
      };

    case ActionType.REMOVE:{
      const next = {...state};
      delete next[action.payload];
      return next;
    }
  }
};

const TodoContext = React.createContext();

export const TodoListProvider = (
  options: React.PropsWithChildren<{ initial: State }>
) => {

  const [selected, setSelected] = useState<string|undefined>();
  const state$ = useObservable(reducer, initial);

  const add = useCallback((item: Emit<TodoItem, 'id'>) => {
    state$.next({ type: ActionType.ADD, payload: item });
  }, [state$]);

  const remove = useCallback((id: string) => {
    state$.next({ type: ActionType.REMOVE, payload: item });
  }, [state$])
  
  return (
    <TodoContext.Provider value={ {state$, add, remove, selected, setSelected} }>
      { options.children }
    </TodoContext.Provider>
  );
}

const TodoDetail = () => {
  const { state$, selected } = useContext(TodoContext);
  const item = useObservableSelectorState(state$, selected)
  return item ? (
    <div>
      <span>ID: {item.id}</span>
      <span>TXT: {item.txt}</span>
    </div>
  ) : null;
}

const AddTodo = () => {
  const { add } = useContext(TodoContext);
  const txtRef = useRef(null);
  const onSubmit = useCallback(() => {
    add({ txt: txtRef.current.value })
  }, [add, txtRef]);
  return (
    <div>
      <input ref={ txtRef } />
      <button onClick={ onSubmit } />
    </div>
  );
};

const TodoList = () => {
  const { state$, setSelected } = useContext(TodoContext);
  const items = useObservableState(state$).next;
  return (
    <ul>
      { Object.entries(items).map(
        ([key,value]) => <li key={key} onClick={ () => setSelected(key) }>{value.txt}</li>
      )}
    </ul>
  )
}

const App = () => {
  return (
    <TodoListProvider initial={ {} }>
      <TodoDetail />
      <TodoList />
      <AddTodo />
    </TodoListProvider>
  )
}

Versions

Current Tags

VersionDownloads (Last 7 Days)Tag
9.0.0-next-663bed8344cc2ca0111705b05045173328b3104d0next
8.4.3403latest

Version History

VersionDownloads (Last 7 Days)Published
8.4.3403
8.4.2615
9.0.0-next-663bed8344cc2ca0111705b05045173328b3104d0
8.4.1480
8.4.032
8.3.3155
8.3.219
8.3.1118
8.3.08
8.2.031
8.1.5178
8.1.42
8.1.31
8.1.20
0.0.0-next-202309151856120
8.1.10
8.1.00
8.0.30
8.0.20
8.0.10
8.0.00
7.0.331
7.0.20
7.0.10
7.0.00
6.0.00
4.0.10
4.0.00
3.0.40
3.0.30
3.0.20
3.0.10
3.0.00
2.5.00
2.4.20
2.4.10
2.4.00
2.3.00
2.2.00
2.1.20
2.1.00
2.0.10
1.5.10
1.5.00
1.4.10
1.4.00
1.3.10
1.3.00
1.2.10
1.2.00
1.1.00
1.0.00
0.4.00
0.3.30
0.3.20
0.3.11
0.3.00
0.2.00
0.1.120
0.1.110
0.1.100
0.1.90
0.1.80
0.1.70
0.1.60
0.1.50
0.1.40
0.1.30
0.1.20
0.1.10
0.1.00
0.0.20
0.0.10

Package Sidebar

Install

npm i @equinor/fusion-observable

Weekly Downloads

1,711

Version

8.4.3

License

ISC

Unpacked Size

177 kB

Total Files

97

Last publish

Collaborators

  • gustav-eikaas
  • eslsa
  • martinforre
  • _odin_