I started doing the typing of my redux and ran into such a problem, namely the typing of useSelector
Here is the hook I'm creating:
import {TypedUseSelectorHook, useSelector} from 'react-redux'
import {RootState} from '../store/create-reducer'
export const UseTypedSelector: TypedUseSelectorHook <RootState> = useSelector
And he returns me an error:
screen
How to solve this problem? For the second day I can't get off the ground, and using useSelector ((state: any) => state? .SESSION) is not an option.
Here is my side:
create-reducer:
import { combineReducers } from 'redux'
import { STATE } from '../session/types'
import { reducer } from '../session/reducers'
const rootReducer = (asyncReducers: object) => {
return (
combineReducers({
...asyncReducers,
[STATE]: reducer,
})
)
}
export default rootReducer
export type RootState = ReturnType<typeof rootReducer>
create-store:
import { applyMiddleware, compose, createStore } from 'redux'
import thunk from 'redux-thunk'
import persistStore from './persist-store'
import persistReducer from './persist-reducer'
const store = (initialState = {}) => {
const middlewares = [thunk]
const enhancers: Array<any> = []
const store = createStore(
persistReducer({}),
initialState,
compose(applyMiddleware(...middlewares), ...enhancers),
)
const persistor = persistStore(store)
return { store, persistor }
}
export default store
index:
export { default as createReducer } from './create-reducer'
export { default as createStore } from './create-store'
export { default as persistReducer } from './persist-reducer'
persist-reducer:
import { persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage'
import createReducer from './create-reducer'
const persistConfig = { key: 'myproject', storage, whitelist: ['session'] }
const reducer = (asyncReducers: any) => persistReducer(persistConfig, createReducer(asyncReducers))
export default reducer
persist-store:
import { persistStore } from 'redux-persist'
const store = (store: any) => persistStore(store, null, () => {})
export default store
Related
I tried to implement Redux-Persist and this is the code I wrote:
import { createStore, combineReducers } from 'redux';
import { usersReducer } from './users';
import { eventsReducer } from './events';
import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
const persistConfig = {
key: 'root',
storage
}
const reducer = combineReducers({ users: usersReducer, events: eventsReducer })
const persistedReducer = persistReducer(persistConfig, reducer);
const store = createStore(persistedReducer);
const persistor = persistStore(store);
export { store, persistor };
My store.js file:
import { createStore, combineReducers } from 'redux';
import { usersReducer } from './users';
import { eventsReducer } from './events';
import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
const persistConfig = {
key: 'root',
storage
}
const reducer = combineReducers({ users: usersReducer, events: eventsReducer })
const persistedReducer = persistReducer(persistConfig, reducer);
const store = createStore(persistedReducer);
const persistor = persistStore(store);
export { store, persistor };
My usersReducer.js file (eventsReducer.js is built like this one):
const initialState = {
loggedIn: false,
thisUser: []
}
export function usersReducer(state = initialState, action) {
switch (action.type) {
case 'users/loggedIn':
return { ...state, loggedIn: action.payload }
case 'users/addUser':
return { ...state, thisUser: action.payload[0] }
case 'users/setActivated':
return { ...state, thisUser: { ...state.thisUser, activated: action.payload } }
case 'clearAll':
return {
thisUser: []
}
default:
return state
}
}
My index.js file:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { Provider } from 'react-redux'
import { store, persistor } from './store/store';
import { PersistGate } from 'redux-persist/integration/react'
ReactDOM.render(
<Provider store={store}>
<PersistGate persistor={persistor}>
<App />
</PersistGate>
</Provider>,
document.getElementById('root')
);
My problem is: Redux-Persist works and is saved in localStorage, but when I refresh the page, my data saved in localStorage with Redux-Persist don't update my local state and will be empty. I think that on any refresh of the page I should get persisted data from localStorage and send back into my Redux state.
I don't know if is correct what I say but I need help how to resolve this problem.
I'm trying to use redux on my current project. However, I can't use the dispatch data to another component.
Here's my code:
Authenticate.js
import { useDispatch, useSelector } from 'react-redux';
import { setLoginDetails } from 'redux/actions/loginActions';
function Authenticate() {
const [data, setData] = useState([]);
const dispatch = useDispatch();
const loginDetails = useSelector((state) => state);
const validateLogin = async() => {
const response = await.get('/api')
let responseValue = response.data.success
if(responseValue === true) {
let responseResp = JSON.parse(response.data.resp)
dispatch(setLoginDetails(responseResp.data.user))
/** here's the console logs
console.log('responseResp',responseResp)
console.log('AuthenticationOAK/responseResp.data.',responseResp.data)
console.log('AuthenticationOAK/responseResp.data.user',responseResp.data.user)
*/
window.location = '/home'
}
else{
//error
}
}
useEffect(()=>{
validateLogin();
},[])
return(
<div>Authenticating....</div>
)
}
export default Authenticate;
loginAction.js
import { ActionTypes } from '../constants/action-types';
export const setLoginDetails = (loginDetails) => {
return {
type: ActionTypes.SET_LOGIN,
payload: loginDetails,
}
}
action-types.js
export const ActionTypes = {
SET_LOGIN: 'SET_LOGIN',
}
loginReducer.js
import { ActionTypes } from '../constants/action-types';
const initialState = {
loginDetails: [],
}
export const loginReducer = (state = initialState, {type, payload}) => {
console.log('loginReducer/state', state)
console.log('loginReducer/payload',payload)
console.log('loginReducer/type', type)
console.log('loginReducer/initialState',initialState)
switch(type){
case ActionTypes.SET_LOGIN:
return {...state, loginDetails: payload}
default:
return state;
}
}
Home.js
import { useSelector } from 'react-redux';
function Home(){
const loginDetails = useSelector((state) => state.allLoginDetails.loginDetails)
const { email, userName, firstName } = loginDetails;
return(
<h1>username {userName}</h1>
)
}
export default Home;
index.js /redux/reducers/index.js
import { combineReducers } from 'redux'
import { loginReducer } from './loginReducer'
const reducers = combineReducers({
allLoginDetails: loginReducer,
});
export default reducers;
store.js
import { createStore } from 'redux'
import reducers from './index'
const store = createStore(
reducers,
{},
);
export dafault store;
Index.js
import React from 'react'
import { render } from 'react-dom'
import App from './App'
import {createStore} from 'redux'
import { Provider } from 'react-redux'
import store from '../src/redux/reducers/store'
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root'));
Below are the result of console logs from Authenticate.js
screenshots of console log from loginReducer.js
Hoping that you can help me with this, I'm having a hard time on this. Tried to use hard coded value on initialState and it's rendering properly. But when I use dynamic data it's not rendering. Thank you in advance. Stay safe!
in this file: Authenticate.js
useEffect(()=>{
Authenticate(); // it must be validateLogin()?
},[])
I have set up my redux store and everything seems alright all imports and exports seems correct to me but I do not seem to have a valid reducer and sagas. Been stuck, what am I doing wrong?
I get this error message
I have a store with the file structure below
Store
configStore.js
index.js
import { applyMiddleware, compose, createStore } from 'redux';
import createSagaMiddleware from 'redux-saga';
import rootReducer from '../components/rootReducer';
export default function configureStore(initialState) {
const sagaMiddleware = createSagaMiddleware();
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
return {
...createStore(
rootReducer,
initialState,
composeEnhancers(applyMiddleware(sagaMiddleware)),
),
runSaga: sagaMiddleware.run,
};
}
import configureStore from './configStore';
import rootSaga from '../components/rootSaga';
const store = configureStore({});
store.runSaga(rootSaga);
export default store;
rootSaga
import { all } from 'redux-saga/effects';
import planets from './planets';
export default function* rootSaga() {
yield all([
planets.sagas(),
]);
}
rootReducer
import { combineReducers } from 'redux';
import planets from './planets';
export default combineReducers({
planets: planets.reducers,
});
In my components I have
reducers.js
import { UPDATE_PLANETS, LOAD_PLANETS } from './actionTypes';
const initialState = {
isPlanetsLoading: false,
planets: [],
};
export default (state = initialState, { type, payload }) => {
switch (type) {
case LOAD_PLANETS:
return {
...state,
isPlanetsLoading: true,
};
case UPDATE_PLANETS:
return {
...state,
isPlanetsLoading: false,
planets: payload,
};
default:
return state;
}
};
Planets.js
import { List } from "antd";
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { requestPlanets } from '../actions';
const Planets = () => {
const dispatch = useDispatch();
const { planets } = useSelector(
(state) => state.planets
);
console.log(planets);
useEffect(() => {
dispatch(requestPlanets());
}, [dispatch, planets]);
// return statement
};
export default Planets;
createStore returns the store. So don't spread it. Just associate the output of createStore to an object property say store.
in index.js, destructure the configStore object { store, runSaga }
configStore
export default function configureStore(initialState) {
const sagaMiddleware = createSagaMiddleware();
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
return {
store: createStore(
rootReducer,
initialState,
composeEnhancers(applyMiddleware(sagaMiddleware)),
),
runSaga: sagaMiddleware.run,
};
}
index.js
import configureStore from './configStore';
import rootSaga from '../components/rootSaga';
const { store, runSaga } = configureStore({});
runSaga(rootSaga);
export default store;
I am trying to update the redux store with a list of groupsNames.
The axios call inside the action works and there is a response.
When I dispatch the payload the redux store doesnt get updated with response data.
FileName: actions/index.js
CODE:
export const getGroups = () => async dispatch => {
axios.get(url + "groups")
.then(response => {
console.log(response.data);
dispatch({
type: GET_GROUPS,
payload: response.data
})
},
function(error) {
console.log(error)
}
);
};
Filename: reducers/groupsReducer.js
CODE:
import _ from 'lodash';
import {
GET_GROUPS,
} from '../actions/types';
export default (state = {}, action) => {
console.log(action.payload);
console.log("inside groupsREducer");
switch (action.payload) {
case GET_GROUPS:
console.log(action.payload);
return {...state, ..._.mapKeys(action.payload, 'id')};
default:
return state;
}
}
//mapKeys is a function from lowdadsh that takes an array and returns an object.
FileName: reducers/index.js
CODE:
import { combineReducers } from 'redux';
import authReducer from './authReducer';
import { reducer as formReducer } from 'redux-form';
import postsReducer from './postsReducer';
import groupsReducer from './groupsReducer';
export default combineReducers ({
auth: authReducer,
form: formReducer,
posts: postsReducer,
groups: groupsReducer,
});
FileName: GroupList.js
CODE:
import React from "react";
import { connect } from "react-redux";
import { getGroups } from '../../actions';
class GroupList extends React.Component {
componentDidMount() {
this.props.getGroups();
}
render() {
return <div>
<h1>GroupList</h1>
</div>;
}
}
export default connect(null, { getGroups })(GroupList);
FileName: App.js
CODE:
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware, compose} from 'redux';
import reduxThunk from 'redux-thunk';
import reducers from './reducers';
import Landing from './components/Landing';
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
reducers,
composeEnhancers(applyMiddleware(reduxThunk))
);
ReactDOM.render(
<Provider store={store}>
<Landing />
</Provider>,
document.querySelector('#root')
);```
Ive connected to ReduxDevToolsExtension in chrome and when i check the state in there, it shows empty.
Your are using the wrong argument for your switch-case.
Replace switch (action.payload) with switch (action.type)
The github repo for this project: https://github.com/leongaban/react_starwars
Expected
My basic app runs without errors, and in the chrome devtools Redux tab, I see a list of star wars characters
Results
The main index.js
import React from 'react'
import ReactDOM from 'react-dom'
import App from './components/App'
import { createStore, applyMiddleware, compose } from 'redux'
import { Provider } from 'react-redux'
import thunk from 'redux-thunk'
import reducer from './reducer'
import { getCharacters } from './reducer/characters/actions'
const store = createStore(reducer, compose(
applyMiddleware(thunk),
window.devToolsExtension ? window.devToolsExtension : f => f
));
store.dispatch(getCharacters())
const container = document.getElementById('app-container');
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>
, container);
My src > reducer > characters > actions.js
import { API_URL } from '../../constants'
export const SET_CHARACTERS = 'SET_CHARACTERS'
export function getCharacters() {
return dispatch => {
fetch(`${API_URL}/people`)
.then(res => res.json())
.then(res => res.results)
.then(characters =>
dispatch(setCharacters(characters))
)
}
}
export function setCharacters(characters) {
return {
type: SET_CHARACTERS,
characters
}
}
reducer > characters > index.js
import { SET_CHARACTERS } from './actions'
const initialState = [];
export default (state = initialState, action) => {
switch(action.type) {
case SET_CHARACTERS:
return action.characters;
default:
return state;
}
}
reducer > index.js
import { combineReducers } from 'redux'
import characters from './characters'
export default combineReducers({
characters
})
try
const createFinalStore = compose(
applyMiddleware(thunk)
)(createStore)
const store = createFinalStore(reducer, initialState /* or {} */);
i don't think the createStore redux api wants you to pass the middleware as the second argument. that should be the initial/preloaded state
http://redux.js.org/docs/api/createStore.html