Kaynağa Gözat

react shop protRout customHook

ivar_n 2 yıl önce
ebeveyn
işleme
ac4fddcb97
1 değiştirilmiş dosya ile 124 ekleme ve 9 silme
  1. 124 9
      js/24_react_shop/react_shop/src/App.js

+ 124 - 9
js/24_react_shop/react_shop/src/App.js

@@ -186,6 +186,12 @@ const actionCartRemove = (good) => ({type: 'CART_REMOVE', good})
 const actionCartClear = () => ({type: 'CART_CLEAR'})
 
 
+function routeReducer(state={}, {type, match}) {
+  if (type === 'ROUTE') {
+      return match
+  }
+  return state
+}
 
 
 function promiseReducer(state={}, {type, status, payload, error, name}) {
@@ -397,7 +403,8 @@ const getGQL = url => (
 const sagaMiddleware = createSagaMiddleware()   
 const store = createStore(  combineReducers({ promise: promiseReducer, 
                               auth: authReducer, 
-                              cart: cartReducer}),
+                              cart: cartReducer,
+                              route: routeReducer}),
                             applyMiddleware(sagaMiddleware))                        
 
 
@@ -450,8 +457,35 @@ function* registerWatcher() {
   yield takeEvery('FULL_REGISTER', registerWorker)
 }
 
+const queries = {
+  "/good/:_id": match => ({ name: 'goodById',
+                            query: `query goodById($q: String) {
+                                        GoodFindOne(query: $q) {
+                                            _id name price description images {
+                                            url
+                                            }
+                                        }
+                                    }`,
+                            variables: {q: JSON.stringify([{_id: match.params._id}])}
+                          })
+}
+
+
+function* routeWorker({match}) {
+  console.log(match)
+  if (match.path in queries) {
+    const {name, query, variables} = queries[match.path](match)
+    yield call(promiseWorker, actionPromise(name, gql(query, variables)))
+  }
+}
+
+function* routeWatcher() {
+  yield takeEvery('ROUTE', routeWorker)
+}
+
 function* rootSaga() {
   yield all([
+    routeWatcher(),
     promiseWatcher(),
     loginWatcher(),
     registerWatcher()
@@ -470,6 +504,79 @@ store.subscribe(() => console.log(store.getState()))
 store.dispatch(actionRootCats())
 
 
+
+
+
+const RRoute = ({ action, component:Component, ...routeProps}) => {
+  const WrapperComponent = (componentProps) => {
+    action(componentProps.match)
+    return <Component {...componentProps} />
+  }
+  return <Route {...routeProps} component={WrapperComponent} />
+}
+const CRRoute = connect(null, {action: match => ({type: 'ROUTE', match})})(RRoute)
+
+const ProtectedRoute = ({ fallback='/',
+                          roles=["admin"],
+                          auth,
+                          component:Component,
+                          ...routeProps}) => {
+
+  const WrapperComponent = (componentProps) => {
+    let aclArr = auth?.payload?.sub?.acl
+    if (!aclArr) {
+      aclArr = ['anon']
+    }
+    let crossArr = [];
+    for (const role of roles) {
+      crossArr = [...crossArr, ...aclArr.filter(aclItem => aclItem === role)] 
+    }
+    if (crossArr.length === 0) {
+      return <Redirect to={fallback} />
+    } else {
+      return <Component {...componentProps} />
+    }
+  }
+  return <CRRoute {...routeProps} component={WrapperComponent} />
+}
+
+const CPRoute = connect(state => ({auth: state.auth}))(ProtectedRoute)
+                          
+
+
+
+const useLocalStoredState = (defaultState, localStorageName) => {
+  let inputJson
+  try {
+    inputJson = JSON.parse(localStorage.getItem(localStorageName))
+  } catch(err) {
+    console.error(err)
+    localStorage.removeItem(localStorageName)
+  }
+  const [state, setState] = useState(inputJson || defaultState)
+
+  return [state, newState => {
+    setState(newState)
+    localStorage.setItem(localStorageName, JSON.stringify(newState))
+  }]  
+}
+
+
+const useProxyState = (defaultState) => {
+  const [state, setState] = useState(defaultState)
+  return new Proxy(state, {
+    get(obj, key) {
+      return obj[key]
+    },
+    set(obj, key, value) {
+      setState({...obj, [key]: value})
+      return true
+    }
+  })
+}
+
+
+
 const Logo = ({logo=logoDefault}) => (
   <Link to='/' className="Logo">
       <img src={logo} />
@@ -779,18 +886,25 @@ const CThisGood = connect(  state => ({good: state.promise.goodById?.payload}),
                             {onCartAdd: actionCartAdd})(ThisGood)
 
 
-const PageGood = ({match:{params:{_id}}, getData}) => {
-  useEffect(() => {
-      getData(_id)
-  },[_id])
 
-  return (
+const PageGood = ({match:{params:{_id}}}) => (
     <>
       <CThisGood />
     </>
   )
-}
-const CPageGood = connect(null, {getData: actionGoodById})(PageGood)
+
+
+// const PageGood = ({match:{params:{_id}}, getData}) => {
+//   useEffect(() => {
+//       getData(_id)
+//   },[_id])
+//   return (
+//     <>
+//       <CThisGood />
+//     </>
+//   )
+// }
+// const CPageGood = connect(null, {getData: actionGoodById})(PageGood)
 
 
 // на текущий момент функция отображает только 100 последних заказов
@@ -861,7 +975,8 @@ const Main = () => (
         <Switch>
           <Route path="/" component={PageMain} exact />
           <Route path="/category/:_id" component={CPageCategory} />
-          <Route path="/good/:_id" component={CPageGood} />
+          {/* <Route path="/good/:_id" component={CPageGood} /> */}
+          <CPRoute roles={['anon', 'user', 'admin']} path="/good/:_id" component={PageGood} />
           <Route path="/cart" component={CCart} />
           <Route path="/login" component={CLoginForm} />
           <Route path="/register" component={CRegisterForm} />