my redux is not working the way i wrote it down - javascript

Lately, I have been trying to use Redux but I get no error and no dev tool error and my page are blank.
So I started my code with the basic Redux boilerplate. I created a userslice, a store and then I provided the store as a wrapper for the <app/>.
Yet after spending hours I can't get to fix the code. Code should just give me back the username inside a div using useselector hook that initialized but it does not seem to work.
App.js:
import React from 'react';
import { useSelector } from 'react-redux';
import './App.css';
function App() {
const username = useSelector(state => state.username)
return (
<div className="App">
{username}
</div>
);
}
export default App;
userSlice.js
import { createSlice } from "#reduxjs/toolkit";
export const userSlice = createSlice({
name:'user'
,
initialState:{
username:'Tony stark',
post:'',
},
reducers:{
updatePost:(state,action)=>{
state.username = action.payload;
}
}})
export const { updatePost} = userSlice.actions;
export default userSlice.reducers;
store.js
import { configureStore } from '#reduxjs/toolkit';
import userSlice from '../redux/userSlice'
export const store = configureStore({
reducer: {
user: userSlice,
},
});
index.js
import React from 'react';
import { createRoot } from 'react-dom/client';
import { Provider } from 'react-redux';
import { store } from '../src/redux/store'
import App from './App';
import './index.css';
const container = document.getElementById('root');
const root = createRoot(container);
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))

As it's in the userSlice you'll need to get it from the user property of the Redux root state, like so:
const username = useSelector(state => state.user.username)
Your initial Redux state (annotated) should look like this:
{ // <-- state
user: { // <-- state.user
username: 'Tony stark', // <-- state.user.username
post: '' // <-- state.user.post
}
}

Related

No Output on DOM after adding Redux Logic

I was trying out react redux, but each time I add redux logic in my App component, I don't get any output on the browser window.
I have three files:
App.js
import React from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { increment } from './counterSlice';
function App() {
const count = useSelector((state) => state.counter.value)
const dispatch = useDispatch()
return (
<div>
<h1>Values is {count}</h1>
<button onClick={() => dispatch(increment)}>Plus</button>
</div>
);
}
export default App;
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { Provider } from 'react-redux';
import store from './store';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);
counterSlice.js
import { createSlice } from "#reduxjs/toolkit";
const counterSlice = createSlice({
name: 'counter',
initialState: {
value: 0
},
reducers: {
increment: state => {
state.value++;
},
decrement: state => {
state.value--;
}
}
});
export const { increment, decrement } = counterSlice.actions;
export default counterSlice.reducer
And finally the store.js
import { configureStore } from "#reduxjs/toolkit";
import counterReducer from "./counterSlice";
const store = configureStore({
reducer: counterReducer
})
export default store;
What could be the problem?
I tried to run the code using npm start and was expecting to see the initial state value stored in the counter slice display in the browser window.

My component is not updating even though my state in redux is updated

I'm kind of new to redux and react and I'm kind of stuck. so I have this webapp that adds a new list to the redux state todos array.
In my redux devtools state the new list is being added properly but the useSelector in my app is not being updated properly and I can't seem to figure out why.
I tried looking it up online and tried different methods but they didn't work ;-;
Sorry if this is a nooby question and ty in advance for any help <3
my App.js file:
import { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { addTask } from './redux/toDoSlice';
import SideBar from './components/SideBar';
function App() {
const lists = useSelector((state)=> state.todos);
return (
<SideBar
lists = {lists}
/>
)
export default App;
toDoSlice.js file:
import {createSlice} from '#reduxjs/toolkit';
const toDoSlice = createSlice({
name: "todos",
initialState: [],
reducers: {
addList: (state , action)=>{
state.push(action.payload.list);
},
}
});
export const {
addList,
} = toDoSlice.actions;
export default toDoSlice.reducer;
my SideBar.js file:
import React, { useState } from "react";
import { useDispatch } from 'react-redux';
import { addList } from "../redux/toDoSlice";
export default function SideBar(props){
const lists = props.lists;
const dispatch = useDispatch();
const addNewListEvent = (e)=>{
e.preventDefault();
var date_time = new Date().toLocaleString();
var title = 'my list '+date_time;
var list = {
_id:date_time,
title:title,
items:[]
};
dispatch(addList({list: list}));
}
return(
<button onClick={addNewListEvent}>New</button>
)
}
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import './index.css';
import App from './App';
import store from './redux/store';
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById('root')
);

Using Expo AppLoading to preload data from firebase

I am trying to use AppLoading on Expo to preload data from firebase, before the app goes to the homepage. I keep receiving an error.
"Error: could not find react-redux context value; please ensure the component is wrapped in a
< Provider > "
import React, { useState } from "react";
import { createStore, combineReducers, applyMiddleware } from "redux";
import { Provider } from "react-redux";
import ReduxThunk from "redux-thunk";
import productsReducer from "./store/productReducer";
import createdProducts from "./store/createdProductReducer";
import storeName from "./store/StoreNameReducer";
import authReducer from "./store/authReducer";
import { useDispatch } from "react-redux";
import * as ProdActions from "./store/productActions";
import AppLoading from "expo-app-loading";
import InventoryNavigator from "./navigation/InventoryNavigator";
const rootReducer = combineReducers({
products: productsReducer,
availableProducts: createdProducts,
auth: authReducer,
storeName: storeName,
});
const store = createStore(rootReducer, applyMiddleware(ReduxThunk));
export default function App() {
const [fireBLoaded, setFireBLoaded] = useState(false);
const dispatch = useDispatch();
const fetchFirebase = () => {
dispatch(ProdActions.fetchAvailableProducts());
dispatch(ProdActions.fetchStoreName());
dispatch(ProdActions.fetchProducts());
};
if (!fireBLoaded) {
return (
<AppLoading
startAsync={fetchFirebase}
onFinish={() => setFireBLoaded(true)}
onError={console.warn}
/>
);
} else {
return (
<Provider store={store}>
<InventoryNavigator />
</Provider>
);
}
}
what I have tried:
const fetchFirebase = async () => {
any help would be greatly appreciated, I am still new to React Native.
The error tells that there is no Redux.Provider when fetching from Firebase.
To fix it, you should also wrap you <AppLoading ... /> into that <Provider store={store}> ....
It should look like following:
<Provider store={store}>
<AppLoading ... />
<Provider/>
Your fetchFirebase function should be async
Like this -
const fetchFirebase = async () => {
// Perform Aysnc operations here...
dispatch(ProdActions.fetchAvailableProducts());
dispatch(ProdActions.fetchStoreName());
dispatch(ProdActions.fetchProducts());
};
I don't see any other errors here Other than this one

How to make on redux store for two windows in Electron

I've made two different windows with react and provide same store. But if i change store data in one window, second window doesn't changed. And idk know how to synchronize.(All Reducers and Actions made as on default React project)
First provide(index.js):
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import {Provider} from 'react-redux';
import store from "../redux/store";
ReactDOM.render(
<Provider store={store}>
<App/>
</Provider>,
document.getElementById("root"))
First App.js:
import React, {useEffect, useState} from 'react';
import {useDispatch, useSelector} from "react-redux";
import {addNumberAction} from "../redux/addNumber";
export default function App() {
const {number} = useSelector(state=>state.testPage)
const dispatch = useDispatch();
let changeNumber = number
return (
<>
<h1>First</h1>
<button onClick={()=>dispatch(addNumberAction(++changeNumber))}>{number}</button>
</>
)
}
Second provide(index.js):
import React from 'react';
import ReactDOM from 'react-dom'
import App from "./App";
import {Provider} from "react-redux";
import store from "../redux/store";
ReactDOM.render(
<Provider store={store}>
<App/>
</Provider>,
document.getElementById("root2")
)
Second App.js:
import React, {useEffect} from 'react';
import {useDispatch, useSelector} from "react-redux";
import {addNumber, addNumberAction} from "../redux/addNumber";
export default function App() {
const {number} = useSelector(state=>state.testPage)
const dispatch = useDispatch();
let changeNumber = number
return (
<>
<h1>Second</h1>
<button onClick={()=>dispatch(addNumberAction(++changeNumber))}>{number}</button>
</>
)
}
They are not the same store. Each time you use <Provider store={store}> it basically create a store for any components inside it. Calling two <Provider store={store}> will create 2 independent store.
I tried to configure redux state to share state between browser’s windows. At the end, I found info, how it can be with hook.
For example,
import React, { useState, useEffect } from "react";
function HelloStorage() {
const [name, setName] = useState("");
useEffect(() => {
localStorage.setItem("name", name);
}, [name]);
useEffect(() => {
const onReceiveMessage = (e) => {
const { key, newValue } = e;
if (key === "name") {
setName(newValue);
}
};
window.addEventListener("storage", onReceiveMessage);
return () => {
window.removeEventListener("storage", onReceiveMessage);
};
}, []);
const handleChange = (e) => {
setName(e.target.value);
};
return <input value={name} onChange={handleChange} />;
}
For this link you can find information, how create a custom React Hook to share state between browser tabs without Redux state.
You can use redux-state-sync for that (https://www.npmjs.com/package/redux-state-sync).
Lets say you create the store currently like this:
import { configureStore } from '#reduxjs/toolkit';
export const store = configureStore({
reducer
});
All you need is adding the middleware to the store:
import { configureStore } from '#reduxjs/toolkit';
import { createStateSyncMiddleware, initMessageListener } from 'redux-state-sync'
export const store = configureStore({
reducer,
middleware: [createStateSyncMiddleware()],
});
initMessageListener(store);

In Redux, reducer doesn't recognise the action object

I'm using Redux for a React project. For some reason, my reducer doesn't recognise the action type sent to it or even the action itself. I get this error TypeError: Cannot read property 'type' of undefined. And I know I'm using dispatch.
The api from the server works fine, I've tested through Postman.
But I don't understand what's happening with redux.
Please, can someone advise me?
Before stamping down my question, I've read many SO posts that looks similar but none has answered my question, hence why I'm asking it here.
Thanks.
Action:
import axios from 'axios';
export const GET_ALL_USERS = 'GET_ALL_USERS';
export const showAllUsers = () => dispatch => {
console.log('USERS ACTION');
return axios
.get('/api/users/all')
.then(res => {
console.log('GETTING ALL USERS ACTION', res);
return dispatch({
type: GET_ALL_USERS,
payload: res.data
});
})
.catch(err => console.log('Oops! Cannot get any users.'));
};
Reducer:
import { GET_ALL_USERS } from '../actions/usersActions';
const InitialState = {
users: null,
loading: false
};
export default function(state = InitialState, action) {
console.log('USERS REDUCER', action);
switch (action.type) {
case GET_ALL_USERS:
return {
...state,
users: action.payload
};
default:
return state;
}
}
React:
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import './index.css';
import App from './containers/App';
import registerServiceWorker from './registerServiceWorker';
import rootReducer from './reducers';
let middleware = [thunk];
const store = createStore(
rootReducer,
{},
compose(
applyMiddleware(...middleware),
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
)
);
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
registerServiceWorker();
React component:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { showAllUsers } from '../../actions/usersActions';
export class Admin extends Component {
constructor(props) {
super(props);
this.state = {};
}
componentDidMount() {
this.props.showAllUsers();
}
render() {
const { users } = this.props;
console.log(`All users in admin`, this.props.users);
return (
<div className="admin">
<h1 className="admin__title">Admin Board</h1>
{this.props.users.map(user => {
return (
<article>
<img src={user.avatar} alt={user.username} />
<p>{user.firstName}</p>
<p>{user.lastName}</p>
<p>{user.username}</p>
<p>{user.email}</p>
</article>
);
})}
</div>
);
}
}
const mapStateToProps = state => ({
users: state.users
});
export default connect(mapStateToProps, { showAllUsers })(Admin);
showAllUsers is async action. You need some middleware to dispatch async action.
Use redux-thunk or redux-saga and integrate it with store.
It will help to perform asynchronous dispatch
import thunkMiddleware from 'redux-thunk';
let middleWares = [thunkMiddleware];
const store = createStore(
rootReducer, applyMiddleware(...middleWares)
)
If you dispatch async action in synchronous way, the error TypeError: Cannot read property type of undefined will be thrown.

Categories