I want to use redux in my react typescript application
I have been able to create redux store and
also dispatch to redux
I want to get the value dispatched to the store
using useSelector but I am getting this error
Too many re-renders. React limits the number of renders to prevent an infinite loop.
My code
UserReducer
export const userReducer = (state=null, action) => {
switch(action.type){
case "LOGIN":
return action.payload;
case "LOGOUT":
return action.payload;
case default:
return state;
}
}
Login.tsx
import React, { useState } from "react";
import {useDispatch, useSelector} from 'react-redux'
const Login = () => {
const reduxState= useSelector((state) => state);
dispatch({
type: "LOGIN",
payload: "token"
});
return (
<div className="__login">
{JSON.stringify(reduxState)}
</div>
)
};
export default Login;
App.tsx
import React from 'react';
function App() {
return (
<div className="App">
<Routes>
<Route path="/login" element={ <Login />} />
</Routes>
</div>
);
}
export default App;
index.tsx
import React from "react";
import { createStore } from "redux";
import { Provider } from "react-redux";
import { composeWithDevTools } from "redux-devtools-extension";
import rootReducer from "./reducers";
// create store
const store = createStore(rootReducer, composeWithDevTools());
ReactDOM.render(
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>,
document.getElementById("root")
);
reportWebVitals();
logout.tsx
Logout is where I click to change the state of the application by removing the token and change the state to null
import React, { useState } from "react";
import {useDispatch, useSelector} from 'react-redux'
const logout= () => {
const reduxState= useSelector((state) => state);
const logoutApp = () => {
dispatch({
type: "LOGOUT",
payload: null
});
}
return (
<div className="__login">
<span onClick={logoutApp}>logout</span>
</div>
)
};
export default logout;
Your dispatch is just inside the login component. react functional component runs everything in the component on its every render.
import React, { useState } from "react";
import {useDispatch, useSelector} from 'react-redux'
const Login = () => {
const reduxState= useSelector((state) => state);
dispatch({ //This dispatch will call on it's every render, so after success login it will call dispatch again, and then again ... it leads to an infinite loop
type: "LOGIN",
payload: "token"
});
return (
<div className="__login">
{JSON.stringify(reduxState)}
</div>
)
};
export default Login;
The best method is to move it to a button click. or to a useEffect.
Method 1, login on button click
import React, { useState } from "react";
import {useDispatch, useSelector} from 'react-redux'
const Login = () => {
const reduxState= useSelector((state) => state);
const login = () => {
dispatch({
type: "LOGIN",
payload: "token"
});
}
return (
<div className="__login">
{JSON.stringify(reduxState)}
<button onClick={login} >login</button>
</div>
)
};
export default Login;
Method 2. Call it in useEffect
import React, { useState,useEffect } from "react";
import {useDispatch, useSelector} from 'react-redux'
const Login = () => {
const reduxState= useSelector((state) => state);
useEffect(() => {
dispatch({
type: "LOGIN",
payload: "token"
});
},[]) //this useEffect will only call on its first render
return (
<div className="__login">
{JSON.stringify(reduxState)}
</div>
)
};
export default Login;