based redux

This commit is contained in:
ntr committed 2022-09-10 18:54:01 +10:00
1 parent 5f853696ab
commit b0572cb63d
8 files changed
+144 -41

No files matched your search

+73
View File
@@ -9,6 +9,7 @@
"version": "0.1.0", "version": "0.1.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@reduxjs/toolkit": "^1.8.5",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"preact": "^10.10.0", "preact": "^10.10.0",
"preact-render-to-string": "^5.2.1", "preact-render-to-string": "^5.2.1",
@@ -2663,6 +2664,29 @@
"webpack": "^4.0.0 || ^5.0.0" "webpack": "^4.0.0 || ^5.0.0"
} }
}, },
"node_modules/@reduxjs/toolkit": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.8.5.tgz",
"integrity": "sha512-f4D5EXO7A7Xq35T0zRbWq5kJQyXzzscnHKmjnu2+37B3rwHU6mX9PYlbfXdnxcY6P/7zfmjhgan0Z+yuOfeBmA==",
"dependencies": {
"immer": "^9.0.7",
"redux": "^4.1.2",
"redux-thunk": "^2.4.1",
"reselect": "^4.1.5"
},
"peerDependencies": {
"react": "^16.9.0 || ^17.0.0 || ^18",
"react-redux": "^7.2.1 || ^8.0.2"
},
"peerDependenciesMeta": {
"react": {
"optional": true
},
"react-redux": {
"optional": true
}
}
},
"node_modules/@rollup/plugin-babel": { "node_modules/@rollup/plugin-babel": {
"version": "5.3.1", "version": "5.3.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
@@ -10063,6 +10087,15 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/immer": {
"version": "9.0.15",
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.15.tgz",
"integrity": "sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/immer"
}
},
"node_modules/import-fresh": { "node_modules/import-fresh": {
"version": "3.3.0", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@@ -16224,6 +16257,14 @@
"@babel/runtime": "^7.9.2" "@babel/runtime": "^7.9.2"
} }
}, },
"node_modules/redux-thunk": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz",
"integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==",
"peerDependencies": {
"redux": "^4"
}
},
"node_modules/regenerate": { "node_modules/regenerate": {
"version": "1.4.2", "version": "1.4.2",
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
@@ -16523,6 +16564,11 @@
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
"dev": true "dev": true
}, },
"node_modules/reselect": {
"version": "4.1.6",
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.6.tgz",
"integrity": "sha512-ZovIuXqto7elwnxyXbBtCPo9YFEr3uJqj2rRbcOOog1bmu2Ag85M4hixSwFWyaBMKXNgvPaJ9OSu9SkBPIeJHQ=="
},
"node_modules/resolve": { "node_modules/resolve": {
"version": "2.0.0-next.4", "version": "2.0.0-next.4",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz",
@@ -23102,6 +23148,17 @@
"@prefresh/utils": "^1.1.2" "@prefresh/utils": "^1.1.2"
} }
}, },
"@reduxjs/toolkit": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.8.5.tgz",
"integrity": "sha512-f4D5EXO7A7Xq35T0zRbWq5kJQyXzzscnHKmjnu2+37B3rwHU6mX9PYlbfXdnxcY6P/7zfmjhgan0Z+yuOfeBmA==",
"requires": {
"immer": "^9.0.7",
"redux": "^4.1.2",
"redux-thunk": "^2.4.1",
"reselect": "^4.1.5"
}
},
"@rollup/plugin-babel": { "@rollup/plugin-babel": {
"version": "5.3.1", "version": "5.3.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
@@ -28975,6 +29032,11 @@
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"immer": {
"version": "9.0.15",
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.15.tgz",
"integrity": "sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ=="
},
"import-fresh": { "import-fresh": {
"version": "3.3.0", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@@ -33670,6 +33732,12 @@
"@babel/runtime": "^7.9.2" "@babel/runtime": "^7.9.2"
} }
}, },
"redux-thunk": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz",
"integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==",
"requires": {}
},
"regenerate": { "regenerate": {
"version": "1.4.2", "version": "1.4.2",
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
@@ -33902,6 +33970,11 @@
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
"dev": true "dev": true
}, },
"reselect": {
"version": "4.1.6",
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.6.tgz",
"integrity": "sha512-ZovIuXqto7elwnxyXbBtCPo9YFEr3uJqj2rRbcOOog1bmu2Ag85M4hixSwFWyaBMKXNgvPaJ9OSu9SkBPIeJHQ=="
},
"resolve": { "resolve": {
"version": "2.0.0-next.4", "version": "2.0.0-next.4",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz",
+1 -1
View File
@@ -9,6 +9,7 @@
"lint": "eslint src" "lint": "eslint src"
}, },
"dependencies": { "dependencies": {
"@reduxjs/toolkit": "^1.8.5",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"preact": "^10.10.0", "preact": "^10.10.0",
"preact-render-to-string": "^5.2.1", "preact-render-to-string": "^5.2.1",
@@ -16,7 +17,6 @@
"react-feather": "^2.0.10", "react-feather": "^2.0.10",
"react-redux": "^8.0.2", "react-redux": "^8.0.2",
"redux": "^4.2.0", "redux": "^4.2.0",
"unistore": "^3.5.2"
}, },
"devDependencies": { "devDependencies": {
"@babel/plugin-transform-react-jsx-source": "^7.18.6", "@babel/plugin-transform-react-jsx-source": "^7.18.6",
+5 -6
View File
@@ -1,9 +1,8 @@
import { h } from 'preact'; import { h } from 'preact';
import { useState, useEffect } from 'preact/hooks'; import { useState, useEffect } from 'preact/hooks';
import { Route, Router, route } from 'preact-router'; import { Route, Router, route } from 'preact-router';
import { Provider, connect } from 'unistore/preact' import { Provider } from 'react-redux'
import createStore from './store';
import createWs from './ws'; import createWs from './ws';
import http from './http'; import http from './http';
@@ -16,17 +15,17 @@ import Login from './routes/login';
import Search from './routes/search'; import Search from './routes/search';
import List from './routes/list'; import List from './routes/list';
const store = createStore(); import store, { userState, wsState } from './store'
const ws = createWs(store);
const ws = createWs(store);
ws.connect(); ws.connect();
async function init() { async function init() {
const [error, user] = await http.getLogin(); const [error, user] = await http.getLogin();
if (error) return route('/login'); if (error) return route('/login');
route('/bundles'); route('/bundles');
store.setState({ user }); store.dispatch(userState.actions.set(user));
store.setState({ ws }); store.dispatch(wsState.actions.set(ws));
} }
init(); init();
+10 -8
View File
@@ -1,15 +1,19 @@
import { h } from 'preact'; import { h } from 'preact';
import { route } from 'preact-router'; import { route } from 'preact-router';
import { connect } from 'unistore/preact' import { useSelector, useDispatch } from 'react-redux'
import http from './../http'; import http from './../http';
import actions from './../actions'; import { State, userState } from './../store';
const Header = ({ user, logout }) => { const Header = () => {
const dispatch = useDispatch()
const user = useSelector((state: State) => state.user);
function logoutClick(e) { async function logoutClick(e) {
e.preventDefault(); e.preventDefault();
logout(); await http.postLogout();
route('/login');
dispatch(userState.actions.set(null));
} }
const nav = () => ( const nav = () => (
@@ -39,7 +43,6 @@ const Header = ({ user, logout }) => {
<a href="/account">Account</a> <a href="/account">Account</a>
<a href="/auth/logout" onClick={logoutClick}>Logout</a> <a href="/auth/logout" onClick={logoutClick}>Logout</a>
</nav> </nav>
) )
return ( return (
@@ -51,5 +54,4 @@ const Header = ({ user, logout }) => {
); );
} }
// @ts-ignore unistore types export default Header;
export default connect(['user'], actions)(Header);
+1 -5
View File
@@ -7,9 +7,7 @@ import AcpOffer from './../components/acp.offer';
import { Status } from './../../../api/src/offers'; import { Status } from './../../../api/src/offers';
function ItemEl({ item, ws }) { function Item({ item, ws }) {
console.log(item);
console.log(ws);
const statuses = Object.entries(Status).map(([label, value]) => ( const statuses = Object.entries(Status).map(([label, value]) => (
<option value={value}>{label}</option> <option value={value}>{label}</option>
)); ));
@@ -32,8 +30,6 @@ function ItemEl({ item, ws }) {
); );
} }
const Item = connect(['ws'], {}, ItemEl);
function SellerGroup(group) { function SellerGroup(group) {
return ( return (
<div class="bundle"> <div class="bundle">
+8 -5
View File
@@ -1,19 +1,22 @@
import { h } from 'preact'; import { h } from 'preact';
import { useState, useEffect } from 'preact/hooks'; import { useState, useEffect } from 'preact/hooks';
import { route } from 'preact-router'; import { route } from 'preact-router';
import { connect } from 'unistore/preact' import { useSelector, useDispatch } from 'react-redux'
import http from './../http'; import http from './../http';
import actions from './../actions'; import { State, offersState } from './../store';
import Offer from './../components/offer'; import Offer from './../components/offer';
function Home({ offers, setOffers }) { function Home() {
const dispatch = useDispatch()
const offers = useSelector((state: State) => state.offers);
useEffect(() => { useEffect(() => {
async function getOffers() { async function getOffers() {
const [error, offers] = await http.getOffers(); const [error, offers] = await http.getOffers();
if (error) return console.error(error); if (error) return console.error(error);
setOffers(offers); dispatch(offersState.actions.set(offers));
if (offers.length === 0) route('/search'); if (offers.length === 0) route('/search');
} }
getOffers(); getOffers();
@@ -35,4 +38,4 @@ function Home({ offers, setOffers }) {
); );
} }
export default connect(['offers'], actions)(Home); export default Home;
+9 -8
View File
@@ -1,12 +1,15 @@
import { h } from 'preact'; import { h } from 'preact';
import { route } from 'preact-router'; import { route } from 'preact-router';
import { useState, useEffect, useRef } from 'preact/hooks'; import { useState, useEffect, useRef } from 'preact/hooks';
import { connect } from 'unistore/preact' import { useSelector, useDispatch } from 'react-redux'
import http from './../http'; import http from './../http';
import actions from './../actions'; import { State, userState } from './../store';
const Login = ({ mode }) => {
const dispatch = useDispatch()
const user = useSelector((state: State) => state.user);
const Login = ({ setUser, mode }) => {
const [email, setEmail] = useState('') const [email, setEmail] = useState('')
const [password, setPassword] = useState(''); const [password, setPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState(''); const [confirmPassword, setConfirmPassword] = useState('');
@@ -16,14 +19,14 @@ const Login = ({ setUser, mode }) => {
const [error, user] = await http.postLogin(email, password); const [error, user] = await http.postLogin(email, password);
if (error) return setError(error); if (error) return setError(error);
route('/'); route('/');
setUser(user); dispatch(userState.actions.set(user));
} }
async function postRegister() { async function postRegister() {
const [error, user] = await http.postRegister(email, password); const [error, user] = await http.postRegister(email, password);
if (error) return setError(error); if (error) return setError(error);
route('/search'); route('/search');
setUser(user); dispatch(userState.actions.set(user));
} }
function handleSubmit(e) { function handleSubmit(e) {
@@ -86,12 +89,10 @@ const Login = ({ setUser, mode }) => {
); );
}; };
const LoginForm = connect([], actions)(Login);
function LoginPage({ mode }) { function LoginPage({ mode }) {
return ( return (
<div class="landing"> <div class="landing">
<LoginForm mode={mode} /> <Login mode={mode} />
<div></div> <div></div>
<div class="info"> <div class="info">
<p>Mates Crates is a record importing service.</p> <p>Mates Crates is a record importing service.</p>
+37 -8
View File
@@ -1,10 +1,39 @@
import unistore from 'unistore' import { createStore, combineReducers } from 'redux'
import { configureStore, createSlice } from '@reduxjs/toolkit'
export default function createStore() { export const userState = createSlice({
return unistore({ name: 'user',
bundles: [], initialState: null,
offers: [], reducers: {
user: null, set: (state, action) => action.payload
ws: null, },
}); });
};
export const offersState = createSlice({
name: 'offers',
initialState: [],
reducers: {
set: (state, action) => action.payload
},
});
export const wsState = createSlice({
name: 'ws',
initialState: null,
reducers: {
set: (state, action) => action.payload
},
});
const reducer = combineReducers({
user: userState.reducer,
offers: offersState.reducer,
ws: wsState.reducer,
});
const store = createStore(reducer);
export default store;
export type State = ReturnType<typeof store.getState>
export type Dispatch = typeof store.dispatch