Can't render redux to other component reactjs - javascript

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()?
},[])

Related

How to configure redux with next js?

I configured redux this way and it works.
This is the _app.js file reconfigured :
import App from 'next/app';
import { Provider } from 'react-redux';
import withRedux from 'next-redux-wrapper';
import store from '../redux/store';
import React from 'react';
class MyApp extends App {
static async getInitialProps({ Component, ctx }) {
const appProps = Component.getInitialProps ? await Component.getInitialProps(ctx) : {};
console.log(appProps);
return {
appProps: appProps
};
}
render() {
const { Component, appProps } = this.props;
return (
<Provider store={store}>
<Component {...appProps} />
</Provider>
);
}
}
const makeStore = () => store;
export default withRedux(makeStore)(MyApp);
This is the index.js file which I've connected to redux :
import { connect } from 'react-redux';
import { callAction } from '../redux/actions/main';
const Index = (props) => {
console.log(props);
return (
<div>
Index js state <button onClick={() => props.callAction()}>Call action</button>
</div>
);
};
const mapStateProps = (state) => ({
name: state.main.name
});
const mapDispatchProps = {
callAction: callAction
};
export default connect(mapStateProps, mapDispatchProps)(Index);
This is the rootReducer file which gets only one reducer named main :
import { main } from './main';
import { combineReducers } from 'redux';
export const rootReducer = combineReducers({
main: main
});
And this is the store.js file :
import { createStore } from 'redux';
import { rootReducer } from './reducers/rootReducer';
const store = createStore(rootReducer);
export default store;
It all works fine but it throws a warning in the console which says :
/!\ You are using legacy implementaion. Please update your code: use createWrapper() and wrapper.withRedux().
What changes to which files I need to make to fix the legacy implementation warning?
I solved the warning by changing the way I get redux states and actions in index.js and the way passing them in _app.js files by using the createWrapper and withRedux :
_app.js
import App from 'next/app';
import store from '../redux/store';
import { Provider } from 'react-redux';
import { createWrapper } from 'next-redux-wrapper';
class MyApp extends App {
render() {
const { Component, pageProps } = this.props;
return (
<Provider store={store}>
<Component {...pageProps} />
</Provider>
);
}
}
const makeStore = () => store;
const wrapper = createWrapper(makeStore);
export default wrapper.withRedux(MyApp);
index.js
import { callAction } from '../redux/action';
import { connect } from 'react-redux';
const Index = (props) => {
return (
<div>
hey {props.name}
<br />
<button onClick={() => props.callAction()}>Call action</button>
</div>
);
};
const mapState = (state) => {
return {
name: state.name
};
};
const mapDis = (dispatch) => {
return {
callAction: () => dispatch(callAction())
};
};
export default connect(mapState, mapDis)(Index);
I would like to leave this answer, it worked for me in TS
================== _app.tsx ==================
import type { AppProps } from 'next/app'
import { Provider } from 'react-redux';
import { createWrapper } from 'next-redux-wrapper';
import { store } from '../redux/store';
function MyApp({ Component, pageProps }: AppProps & { Component: { layout: any }}) {
const Layout = Component.layout || (({ children }) => <>{children}</>);
return (
<Provider store={store}>
<Layout>
<Component {...pageProps} />
</Layout>
</Provider>
);
}
MyApp.getInitialProps = async ({ Component, router, ctx }) => {
const pageProps = Component.getInitialProps ? await Component.getInitialProps(ctx) : {};
return { pageProps };
}
const makeStore = () => store;
const wrapper = createWrapper(makeStore);
export default wrapper.withRedux(MyApp);
================== store.tsx ==================
import { applyMiddleware, createStore } from 'redux';
import thunkMiddleware from 'redux-thunk';
import { composeWithDevTools } from 'redux-devtools-extension';
import { rootReducer } from '../reducers';
export const store = createStore(
rootReducer,
composeWithDevTools(applyMiddleware(thunkMiddleware)),
);
export type AppDispatch = typeof store.dispatch;
================== reducers.tsx ==================
import * as redux from 'redux';
import { ThunkDispatch } from 'redux-thunk';
import { Action } from 'typesafe-actions';
import user from './user';
export const rootReducer = redux.combineReducers({
user,
});
export type AppThunkDispatch = ThunkDispatch<RootState, void, Action>;
export type RootState = ReturnType<typeof rootReducer>;
================== onereducer.tsx ==================
import { HYDRATE } from "next-redux-wrapper";
import { Reducer } from 'redux';
import { ActionType } from 'typesafe-actions';
import { USER_ACTIONS } from '../../actions/types';
import { IUserData } from './types';
const userState: IUserData = {
_id: '',
email: '',
password: '',
role: '',
};
const userReducer: Reducer<IUserData, ActionType<any>> = (
state = userState,
action,
) => {
switch (action.type) {
case HYDRATE:
return { ...state, ...action.payload.userData };
case USER_ACTIONS.SET_USER_DATA:
return { ...state, ...action.payload.userData };
default:
return { ...state };
}
};
export default userReducer;
PD: Still a work in progress but works!

No reducer provided for key {name}

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;

How do i access redux state from another react component?

I am developing a lottery statistics app that gets data from a csv loaded from an input then I was wanting to read this data to the redux store so I can use it across multiple components.
I have successfully saved the data to the redux store once I import the file and read it through Header.js and using an action, but I am not sure how to access this in other components like e.g. Main.js.
I feel like I am still confused on how react/redux all fits together. I'm sorry if this has been asked before but everything I looked up online I couldn't get to work.
// index.js
import React from "react";
import ReactDOM from "react-dom";
import { createStore, applyMiddleware } from "redux";
import { Provider } from "react-redux";
import thunk from "redux-thunk";
import reducers from "./reducers";
import App from "./components/App";
const store = createStore(reducers, applyMiddleware(thunk));
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.querySelector("#root")
);
// App.js
import React from "react";
import Header from "./Header";
import Main from "./Main";
const App = () => {
return (
<div>
<Header />
<Main />
<div className="numbers-for-draw"></div>
</div>
);
};
export default App;
// Header.js
import React from "react";
import { CSVReader } from "react-papaparse";
import { fetchData } from "../actions";
import { connect } from "react-redux";
class Header extends React.Component {
constructor(props) {
super(props);
this.fileInput = React.createRef();
}
handleReadCSV = data => {
this.props.fetchData(data);
console.log(this.props.data);
};
handleOnError = (err, file, inputElem, reason) => {
console.log(err);
};
handleImportOffer = () => {
this.fileInput.current.click();
console.log("Got to handleImportOffer");
};
render() {
return (
<header>
<CSVReader
onFileLoaded={this.handleReadCSV}
inputRef={this.fileInput}
style={{ display: "none" }}
onError={this.handleOnError}
/>
<button onClick={this.handleImportOffer}>Import</button>
</header>
);
}
}
//Map what is in the redux store (e.g. state) to props
const mapStateToProps = state => ({
data: state.data
});
export default connect(mapStateToProps, {
fetchData: fetchData
})(Header);
// Main.js
import React from "react";
import { fetchData } from "../actions";
import { connect } from "react-redux";
const Main = () => {
console.log("In main");
console.log(this.props.data); //Blows up here.
return <div>Main</div>;
};
//Map what is in the redux store (e.g. state) to props
const mapStateToProps = state => ({
data: state.data
});
export default connect(mapStateToProps, {
fetchData: fetchData
})(Main);
// actions/index.js
export const fetchData = data => dispatch => {
console.log("Action");
const lottoData = {
stringNumbers: [
"one",
"two",
"three",
...
],
allResults: [],
winningNumbers: [],
winningNumbersAsStrings: []
};
const localData = data.data;
localData.shift();
localData.forEach(line => {
const lineObject = {
draw: line[0],
drawDate: line[1],
ballOne: line[2],
ballTwo: line[3],
ballThree: line[4],
ballFour: line[5],
ballFive: line[6],
ballSix: line[7],
bonusBall: line[8],
bonusBall2: line[9],
powerBall: line[10]
};
lottoData.allResults.push(lineObject);
let nums = [];
nums.push(parseInt(line[2]));
nums.push(parseInt(line[3]));
nums.push(parseInt(line[4]));
nums.push(parseInt(line[5]));
nums.push(parseInt(line[6]));
nums.push(parseInt(line[7]));
nums.sort((a, b) => {
if (a < b) {
return -1;
} else if (a > b) {
return 1;
} else {
return 0;
}
});
lottoData.winningNumbers.push(nums);
lottoData.winningNumbersAsStrings.push(nums.toString());
});
dispatch({ type: "FETCH_DATA", payload: lottoData });
};
// lottoReducer.js
export default (state = {}, action) => {
switch (action.type) {
case "FETCH_DATA":
return action.payload;
default:
return state;
}
};
// reducers/index.js
import { combineReducers } from "redux";
import lottoReducer from "./lottoReducer";
export default combineReducers({
data: lottoReducer
});
I haven't tested your code, but it seems to me that the only problem is in your Main.js
While you use a function component and not a class, you shouldn't use this to access your props. The following should work as expected:
const Main = (props) => {
console.log("In main");
console.log(props.data);
return <div>Main</div>;
};
//Map what is in the redux store (e.g. state) to props
const mapStateToProps = state => ({
data: state.data
});
export default connect(mapStateToProps, {
fetchData: fetchData
})(Main);
In your main.js you used functional components so this.props doesn't work there. You must pass props to your component and console.log(props.data).

React.js Redux actions and reducers do not get initated

I am having an issue with my React-Redux app. I have created Redux action & reducer and connected them to my React component. However, it seems like it never gets to my Redux action & reducer.
I put "debugger" in my action and reducer but those debuggers never get initiated.
Could you please help me fix this issue?
Am I missing something here?
Here the current codes in the following files:
Here is the code for my app.js:
import React, { Component } from 'react';
import { render } from 'react-dom';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import ReduxPromise from 'redux-promise';
import rootReducer from './reducers';
import App from './components/index';
const createStoreWithMiddleware = applyMiddleware(thunk, ReduxPromise)(createStore);
render(
<Provider store={createStoreWithMiddleware(rootReducer)}>
<App />
</Provider>,
document.getElementById('app')
);
Here is my code for index.js:
As you can see below, I put a debugger in the "componentDidMount()", and when In run it, it gets to that point.
import React, { Component } from 'react';
import { render } from 'react-dom';
import { connect } from 'react-redux';
import * as AllNewsApiActions from '../actions/newsApiActions';
import '../../css/style.css';
class App extends Component {
componentDidMount() {
this.props.getNewsApi();
debugger;
}
render() {
return (
<div>
<p>Hello from react</p>
<p>Sample Testing</p>
</div>
);
}
}
const mapStateToProps = (state) => ({
newNews: state.newNews
});
export default connect(mapStateToProps, {
...AllNewsApiActions
})(App);
Here is my action:
import * as types from './newsTypes';
const API_KEY = "6c78608600354f199f3f13ddb0d1e71a";
export const getNewsApi = () => {
debugger;
return (dispatch, getState) => {
dispatch({
type: 'API_REQUEST',
options: {
method: 'GET',
endpoint: `https://newsapi.org/v2/top-headlines?country=us&category=business&apiKey=${API_KEY}`,
actionTypes: {
success: types.GET_NEWS_API_SUCCESS,
error: types.GET_NEWS_API_ERROR
}
}
});
}
}
Here is my reducer:
import * as types from '../actions/newsTypes';
const initialState = {
newNews: []
};
const getNewsAPIReducer = (state = initialState, action) => {
switch(action.type) {
case types.GET_NEWS_API_SUCCESS:
debugger;
return { ...state, newNews: action.data };
case types.GET_NEWS_API_ERROR:
debugger;
return { ...state, error: action.data };
default: {
return state;
};
};
};
export default getNewsAPIReducer;
Here is the index.js file in the reducer folder:
import { combineReducers } from 'redux';
import NewsApiReducer from './newsApiReducer.js';
const rootReducer = combineReducers({
newNews: NewsApiReducer
});
export default rootReducer;

React-Redux Uncaught Error: Expected the reducer to be a function

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

Categories

Resources