Reputation: 576
am new to redux and react.
I have just gone through some redux tutorial and started to implement some sue cases .. And one use case i really want is i need a state that i should get in all components,so thats possible with redux as globalized state.
I have a scenario,an api call and i should get this api response in all my components using redux. But thats not happening.
I have index.js as
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { createStore } from "redux";
import allReducer from "./reducers";
import { Provider } from "react-redux";
import "./styles.css";
let store = createStore(
allReducer,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);
const rootElement = document.getElementById("root");
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
rootElement
);
My reducer as
var userArray = [];
fetch("https://jsonplaceholder.typicode.com/users")
.then(res => res.json())
.then(
result => {
console.log(result);
userArray = result;
},
error => {}
);
const IsLoggedReducer = (state, action) => {
console.log(userArray);
switch (action.type) {
case "SIGNIN":
return (state = userArray);
case "LOGGEDOUT":
return (state = userArray);
default:
return (state = userArray);
}
};
export default IsLoggedReducer;
and my app.js as
import React from "react";
import { useSelector } from "react-redux";
function App() {
const counter1 = useSelector(state => state.counterReducer);
const isLogged = useSelector(state => state.IsLoggedReducer);
return (
<h1>
This {counter1}
<ul>
{isLogged.length > 0
? isLogged.map(item => {
return <li key={item.id}>{item.name}</li>;
})
: "No data"}
</ul>
</h1>
);
}
export default App;
when initial load its coming as null array and when i make some edit t the component and save ,it gets data and gets populated..
Here is the code https://codesandbox.io/embed/quirky-sunset-s95gu?fontsize=14
Any help is much appreciated
Upvotes: 0
Views: 1408
Reputation: 1223
I hope this simple codes for action and reducer can help you understand react-redux.
For action
,
export const signin = (userArray) => {
return {
type: "SIGNIN",
payload: userArray,
};
};
export const loggedout = (userArray = []) => {
// You can do something for making users logged out here using userArray and return changed value using payload
// Or just return [] as payload because it's logged out
return {
type: "LOGGEDOUT"
payload: userArray,
};
};
export const initiate = (userArray) => {
return {
type: "INITIATE",
payload: userArray,
}
}
For reducer
, please consider reducer as changer of state.
const IsLoggedReducer = (state = initialState, action) => {
switch (action.type) {
case "SIGNIN":
return action.payload;
case "LOGGEDOUT":
return action.payload;
case "INITIATE":
return action.payload;
default:
return state;
}
};
When it comes to calling api, I want to recommend to use redux-saga
or redux-thunk
but if you need calling api just one time at the beginning of the component. You may be able to use useEffect
(https://reactjs.org/docs/hooks-effect.html) as componentDidMount
is used for calling api in a class component.
And I hope this useEffect code can help you get the feeling
import { useSelector, useDispatch } from 'react-redux';
import { initiate } from 'actions';
function main () {
const state = useSelector((state) => state.user);
const dispatch = useDispatch();
const onInit = useCallback((data) => dispatch(initiate(data), [dispatch]);
useEffect(() => {
// call api and get response
const userArray = fetch();
onInit(userArray);
}, []);
return (<div>...</div>);
}
Upvotes: 1
Reputation: 1710
Ok you are not doing some things in a right way
1 - As API calling is an asynchronous task so you need to handle it, I would recommend write some action creator which does this API calling for you, and when you get the response from API then dispatch appropriate action to update the store state.
2- In your reducer you are mutating the state, don't mutate the previous state, instead return new state object from previous state
Hope it helps
Upvotes: 0