refactoring context

This commit is contained in:
Jean Jacques Avril 2022-03-08 15:10:19 +01:00
parent d990c46a02
commit 6e3419019b
10 changed files with 40 additions and 73 deletions

View File

@ -2,12 +2,15 @@ import { Component, h } from "preact";
import { Router, route } from "preact-router"; import { Router, route } from "preact-router";
import Header from "./header"; import Header from "./header";
import Menu from "./menu"; import Menu from "./menu";
import { useCallback, useState } from "preact/hooks"; import { useCallback, useReducer, useState } from "preact/hooks";
import { AppData, Provider, Consumer } from '../utils'; import { AppData, AppDataProvider } from '../utils';
import { Home, Users, Profile, Login, Logout } from "../route"; import { Home, Users, Profile, Login, Logout } from "../route";
import { AppStateProvider } from "../store/AppState";
class App extends Component { class App extends Component {
// useReducer
appdata = AppData(); appdata = AppData();
session = this.appdata.get("Session"); session = this.appdata.get("Session");
menutoggle = this.appdata.get("menutoggle");
toggleMenu = () => { toggleMenu = () => {
const [visible, setValue] = useState(false); const [visible, setValue] = useState(false);
@ -37,19 +40,17 @@ class App extends Component {
}; };
render() { render() {
let menu = this.toggleMenu(); let menu = this.toggleMenu();
const [menu_shown, toggle_menu] = useReducer(menuReducer,false);
this.menutoggle.data = menu;
let session = this.session; let session = this.session;
session.addAction("isAuth", () => { return session.data && session.data.username !== '' }) session.addAction("isAuth", () => { return session.data && session.data.username !== '' })
console.log(session.actions); console.log(session.actions);
this.sub = session.sub(() => this.forceUpdate()); session.sub(this);
return ( return (
<Provider appdata={this.appdata} > <AppDataProvider>
<AppStateProvider value={{menu_shown, toggle_menu}} >
<div id="wrapper"> <div id="wrapper">
<Consumer datapath="Session">
{(appdata) => {
console.log(appdata);
}}
</Consumer>
<Header menu={menu} /> <Header menu={menu} />
<div class="page"> <div class="page">
<Menu menu={menu} items={this.menu_items} /> <Menu menu={menu} items={this.menu_items} />
@ -73,8 +74,8 @@ class App extends Component {
</footer> </footer>
</div> </div>
</AppStateProvider>
</Provider> </AppDataProvider>
); );
} }

8
src/reducers/reducers.js Normal file
View File

@ -0,0 +1,8 @@
export const menuReducer=(state,action)=>{
switch(action){
case 'show': return true;
case 'hide': return false;
case 'toggle': return !state;
default: throw new Error("menustate unknown to reducer");
}
}

6
src/store/AppState.js Normal file
View File

@ -0,0 +1,6 @@
import { createContext } from "preact";
const AppState = createContext({});
export const AppStateProvider = AppState.Provider;
export default AppState;

View File

@ -4,7 +4,8 @@ function Consumer(props, ctx){
} }
if(props.datapath!==undefined) if(props.datapath!==undefined)
return props.children(ctx.get(props.datapath)); ctx = ctx.get(props.datapath);
ctx.sub(this);
return props.children(ctx); return props.children(ctx);
} }
export default Consumer; export default Consumer;

View File

@ -1,10 +1,9 @@
function subscribe (f) { function subscribe (c) {
if ('function' !== typeof (f))
throw new Error("Subscriber needs to be a function."); this.observers.push(c);
this.observers.push(f); return () => { this.observers.splice(this.observers.indexOf(c), 1) }
return () => { this.observers.splice(this.observers.indexOf(f), 1) }
} }
function getStore(path){ function getStore(path){
let path_slices = path.split("/"); let path_slices = path.split("/");
@ -25,7 +24,7 @@ function ObservableData() {
this._data = {}; this._data = {};
this._actions = {}; this._actions = {};
const dispatchChange = () => { const dispatchChange = () => {
this.observers.map(o => o()); this.observers.map(c=>c.forceUpdate());
} }
return { return {
tree:this.tree, tree:this.tree,

View File

@ -1,22 +1,15 @@
import ObservableData from './ObservableData' import ObservableData from './ObservableData'
import Provider from './Provider' import Provider from './Provider'
import Consumer from './Consumer'
let instance = null; let root = null;
function AppData() { function AppData() {
if(instance===null){ if(root===null){
console.log("New AppData created") console.log("New AppData created")
const root = new ObservableData(); root = new ObservableData();
root.get("affe1234/123"); root.get("affe1234/123");
instance = {
data: root.data,
get: root.get,
Provider: Provider.bind(this),
Consumer: Consumer.bind(this),
}
} }
return instance; return root;
} }
export const AppDataProvider = (props)=><Provider {...props} appdata={AppData()} />
export default AppData; export default AppData;

View File

@ -1,40 +0,0 @@
import {createContext} from 'preact';
class Session {
static instance=null;
observers = [];
static getInstance(){
if(this.instance==null)
this.instance = new Session();
return this.instance;
}
constructor(){
console.log("new Instance of Session manager created");
this.state={token:null,expiry:null,name:null}
}
observe(o){
this.observers.push(o);
}
get Context(){
return createContext(this);
}
setState(updated){
this.state = {...this.state,...updated}
this.observers.map(o=>o.forceUpdate());
console.log(this.state);
}
Login(username, password) {
if (username == "admin" && password == "admin")
{ this.setState({token:"TEST",expiry: new Date(Date.now() + 60000*60),name:username});
return true;
}
return false;
}
Logout = () => this.setState({token:null,expiry:null,name:null});
get isAuthenticated(){
return this.state.token!=null
}
}
export default ()=> Session.getInstance();

View File

@ -1,5 +1,4 @@
import AppData from './appdata' import AppData, {AppDataProvider} from './appdata'
import oldSession from './appdata/oldSession';
import Provider from './appdata/Provider'; import Provider from './appdata/Provider';
import Consumer from './appdata/Consumer'; import Consumer from './appdata/Consumer';
export {AppData, Provider, Consumer, oldSession}; export {AppData, AppDataProvider, Provider, Consumer}