Skip to main content

useReducer Hook + Context API for Towneley project

To ger rid of Redux!!

simpler, more straightforward way to handle global state management

library we are using for this project are:
1. Formik
2. Material Design
3. Redux

1. Index.js
import { StateProvider } from './store.js'
const hist = createBrowserHistory()
const app = (
<StateProvider>
<Router history={hist}>
<Switch>
<Route path='/landing-page' component={LandingPage} />
<Route path='/profile-form' component={ProfileForm} />
<Route path='/privacy-notice' component={PrivacyNotice} />
<Route path='/login-page' component={LoginPage} />
<Route path='/' component={LandingPage} />
</Switch>
</Router>
</StateProvider>
)
ReactDOM.render(app, document.getElementById('root'))
view raw index.js hosted with ❤ by GitHub
2. store.js
import React, { createContext, useReducer } from 'react'
import types from './store/typesOfAction'
import { useActions } from './store/actions'
import { reducer } from './store/reducers'
import applyMiddleware from './store/middleware'
import axios from 'axios'
const initialState = {
profileData: {},
loading: false,
message: ''
}
const store = createContext(initialState)
const { Provider } = store
const StateProvider = ({ children }) => {
const [state, dispatch] = useReducer(reducer, initialState)
const actions = useActions(state, applyMiddleware(dispatch))
return <Provider value={{ state, actions }}>{children}</Provider>
}
export { store, StateProvider }
view raw store.js hosted with ❤ by GitHub
3. reducer.js
import types from './typesOfAction'
const reducer = (state, action) => {
switch (action.type) {
case types.SET_LOADING_INDICATOR:
return { ...state, loading: true }
case types.SAVE_PROFILE_DATA:
return { ...state, profileData: action.profileData }
case types.INCREMENT:
return { ...state, count: state.count + 1 }
case types.DECREMENT:
return { ...state, count: state.count - 1 }
case types.LOAD_PROFILE_DATA_SUCCESS:
return { ...state, projectsOfSat: action.payload, loading: false }
case types.LOAD_PROFILE_DATA_FAIL:
return {
...state,
projectsOfSat: undefined,
loading: false,
message: action.payload
}
default:
throw new Error()
}
}
export { reducer }
view raw reducers.js hosted with ❤ by GitHub
4. actions.js
import types from './typesOfAction'
export const useActions = (state, dispatch) => ({
increment: () => {
dispatch({ type: types.INCREMENT })
},
decrement: () => {
dispatch({ type: types.DECREMENT })
},
saveProfile: values => {
dispatch({
type: types.SET_LOADING_INDICATOR
})
dispatch({
type: types.SAVE_PROFILE_DATA,
profileData: values
})
},
loadProfile: values => {
dispatch({
type: types.SET_LOADING_INDICATOR
})
dispatch({
type: types.LOAD_PROFILE_DATA
})
}
})
view raw actions.js hosted with ❤ by GitHub
5. middleware.js
import types from './typesOfAction'
import axios from 'axios'
const applyMiddleware = dispatch => action => {
switch (action.type) {
case types.LOAD_PROFILE_DATA:
return axios({
url: 'your url...',
method: 'post',
data: {
query: `
query {
projectsOfSat{
projectName
}
}
`
}
})
.then(res => {
console.log(res.data)
dispatch({
type: types.LOAD_PROFILE_DATA_SUCCESS,
payload: res.data.data.projectsOfSat
})
})
.catch(err =>
dispatch({
type: types.LOAD_PROFILE_DATA_FAIL,
payload: err.response
})
)
default:
dispatch(action)
}
}
export default applyMiddleware
view raw middleware.js hosted with ❤ by GitHub
6. typeOfActions.js
export default {
SET_LOADING_INDICATOR: 'SET_LOADING_INDICATOR',
LOAD_PROFILE_DATA: 'LOAD_PROFILE_INFO',
LOAD_PROFILE_DATA_SUCCESS: 'LOAD_PROFILE_DATA_SUCCESS',
LOAD_PROFILE_DATA_FAIL: 'LOAD_PROFILE_DATA_FAIL',
SAVE_PROFILE_DATA: 'save',
}
7. profileForm.js
const { state, actions } = useContext(store)
useEffect(() => {
actions.loadProfile()
}, [])
return (
...
<Formik
initialValues={profileData}
onSubmit={(values, { setSubmitting }) => {
setTimeout(() => {
actions.saveProfile(values)
}, 400)
}}
>
<Form>...</Form>
</Formik>
...
)
view raw profileForm.js hosted with ❤ by GitHub
=======
Same idea - use hook for Material Design
import React from 'react';
import ReactDOM from 'react-dom';
import { ThemeProvider } from '@material-ui/core/styles';
const theme = {};
function App() {
return (
<ThemeProvider theme={theme}>...</ThemeProvider>
);
}
ReactDOM.render(<App />, document.querySelector('#app'));
/*
This hook returns the theme object so it can be used inside a function component.
*/
import React from 'react';
import { useTheme } from '@material-ui/core/styles';
export default function MyComponent() {
const theme = useTheme();
return <div>{`spacing ${theme.spacing}`}</div>;
}
view raw material hosted with ❤ by GitHub

Comments

Popular posts from this blog

for loop in javascript - promise - .eslintrc for "for of"

the vast majority of cases  map ,  forEach ,  find  etc. can be used.  async function printFiles () { const files = await getFilePaths(); await Promise.all(files. map (async (file) => { const contents = await fs.readFile(file, 'utf8') console.log(contents) })); } const inventory = [ { name : 'apples' , quantity : 2 } , { name : 'bananas' , quantity : 0 } , { name : 'cherries' , quantity : 5 } ] ; const result = inventory . find ( ( { name } ) => name === 'cherries' ) ;   function getFirstMatching(array) { for (let item of array) { const result = heavyTransform(item); if (result) { return result; } } } Specifically this shuts down the whole no-restricted-syntax. If you want to cherry-pick, here is the current definition: 'no-restricted-syntax' : [ 'error' , { selector : 'ForInStatement' , message...

Apollo client - cache APIs - auto update cache - erase cache - reactive variables - deletion - addition

Apollo Client 3  Local only fields Reactive Variables const cache = new InMemoryCache ( { typePolicies : { Todo : { // If one of the keyFields is an object with fields of its own, you can // include those nested keyFields by using a nested array of strings: keyFields : [ "date" , "user" , [ "email" ] ] , } } , } ) ; This internal data is intended to be easily  JSON-serializable , so you can take a snapshot with  cache.extract() , save it somewhere, and later restore with  cache.restore(snapshot) . Here’s a mutation called  EditTodo  that returns the new  todo  value in the mutation response. mutation EditTodo ( $id : Int ! , $text : String ! ) { editTodo ( id : $id , text : $text ) { success todo { # <- Returning it here id text completed } error { ... on TodoNotFoundError { message } ... on TodoValidationE...

window.URL.createObjectURL is not (yet) available in jest-dom - testing scenario

Since  window.URL.createObjectURL  is not (yet) available in jest-dom, you need to provide a mock implementation for it. Don't forget to reset the mock implementation after each test. describe ( "your test suite" , () => { window . URL . createObjectURL = jest . fn (); afterEach (() => { window . URL . createObjectURL . mockReset (); }); it ( "your test case" , () => { expect ( true ). toBeTruthy (); }); });