Redux state is undefined in mapStateToProps couldn't find the issue - reactjs

I cannot find out my error. I tried lot of answers in stackoverflow but those didn't work for me.
This is my Reducer: IcmWebReducer.js
const initialState = {
invoices : [],
params: {
status: 'Pending',
_sort: 'documentInfo.dueDate',
_order: 'desc',
q: ''
}
};
const IcmWebReducer = (state = initialState, action) =>{
switch (action.type){
case 'UPDATE_INVOICES':
return Object.assign({}, state, {
invoices: action.invoices
});
case 'UPDATE_PARAMS':
return Object.assign({}, state, {
params: action.params
});
default:
return state;
}
};
export default IcmWebReducer;
This is my App.js
import React, {Component} from 'react';
import './App.scss';
import Header from './components/header/Header'
import InvoiceAudit from "./components/invoice/InvoiceAudit";
class App extends Component {
render() {
return (
<div className="App container">
<Header/>
/* <InvoiceAudit store = {this.props.store}/> */
<InvoiceAudit/>
</div>
);
}
}
export default App;
This is the index.js
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import IcmWebReducer from "./reducers/IcmWebReducer";
let store = createStore(IcmWebReducer);
ReactDOM.render(
<Provider store={store}>
<App/>
</Provider>, document.getElementById('root'));
This is the class that i am using mapStateToProps method
const mapStateToProps = (state) => {
console.log(state);
return {
invoices: state.IcmWebReducer,
}
};
This showed me undefined in console.log . but i can't find the error. I am returning the default state in my reducer also. Can anyone help me

While exporting your app, you should use connect;
export default connect(mapStateToProps)(App)
This might help solve your problem;
const ConnectedApp = connect(mapStateToProps)(App);
And in index.js;
ReactDOM.render(< Provider store={store}>< ConnectedApp /></Provider>, document.getElementById('root'));
Also in your mapStateToProps, this would suffice
const mapStateToProps = (state) => {
console.log(state);
return {
invoices: state.invoices,
//status: state.params.status -> like this
}
I believe problem might be that your invoices state is trying to take whole reducer initial state rather than just invoices empty array.

Your App component should use connect method
App component should be like below snippet
import React, {Component} from 'react';
import {connect} from "react-redux";
import './App.scss';
import Header from './components/header/Header'
import InvoiceAudit from "./components/invoice/InvoiceAudit";
class App extends Component {
render() {
return (
<div className="App container">
<Header/>
<InvoiceAudit/>
</div>
);
}
}
const mapStateToProps = state => ({invoices: state.IcmWebReducer});
export default connect(mapStateToProps)(App);

Related

React Native - Redux

So, im getting started with react native and redux. I'm trying to setup a basic app state, just a counter property to increment when a button is pressed.
Basically, no error is thrown but the state doesnt get updated, at least in the screen the counter keeps having the same value.
Ill try to document the code bellow.
App.js - its where I create the store and a basic reducer
import {createStore} from 'redux'
import {Provider} from 'react-redux'
import App from './src/App'
const initialState = { counter: 0 }
const reducer = (state=initialState, action) {
switch(action.type)
{
case 'INCREASE_COUNTER':
return {counter: state.counter++}
}
return state;
}
const store = createStore(reducer)
class AppProvider extends React.Component {
render() {
return (
<Provider store={store}>
<App />
</Provider>
)
}
}
export default AppProvider
./src/App.js - its where i have the View implemented
import {connect} from 'react-redux';
class App extends React.Component {
render() {
return (
<View>
<Button title="increase" onPress={this.props.increaseCounter}/>
<Text>Counter: {this.props.counter}</Text>
</View>
)
}
}
function mapStateToProps(state) {
return {counter: state.counter};
}
function mapDispatchToProps(dispatch) {
return {
increaseCounter: () => dispatch({type: 'INCREASE_COUNTER'}),
};
}
export default connect(mapStateToProps)(App);
So no error is thrown but the screen still shows Counter: 0 as I press the button.
I'm probably missing something here.
Any help would be awesome.
Thanks and happy programming!
I guess you should pass mapDispatchToProps to connect function.
export default connect(mapStateToProps, mapDispatchToProps)(App);
https://react-redux.js.org/api/connect

How to fix Uncaught TypeError: Cannot read property 'getState' of undefined?

I am trying to use React with Redux for the frontend part with django rest framework in the backend. Got the issue getState in Provider tag in App component because of issue in store. And when i try to use the map function in the Words.js, I get error of undefined use of map. And I believe this is because of value of the array is null. Hence to fixed this error of getState.
Got this error even on including the store in Provider of App component when a reducers was not defined.
When I load a static array it does get rendered properly in the specific component.
This is Redux Store in the filename:store.js
import { createStore, applyMiddleware } from "redux";
import { composeWithDevTools } from 'redux-devtools-extension';
import thunk from 'redux-thunk';
import rootReducer from './reducers'
const initialState = {};
const middleware = [thunk];
const enhancer = composeWithDevTools(applyMiddleware(...middleware));
const store = createStore(
rootReducer,
initialState,
enhancer
);
export default store;
The index.js file is below
import App from './components/App'
import ReactDOM from 'react-dom';
import React from 'react';
ReactDOM.render(<App />, document.getElementById("app"));
They action types file types.js using django rest_framework to create the data.
export const GET_WORDS = "GET_WORDS";
The action file words.js
import { GET_WORDS } from "./types";
import axios from 'axios';
export const getWords = () => dispatch => {
axios.get('/api/words/')
.then(res => {
dispatch({
type: GET_WORDS,
payload: res.data
});
}).catch(err => console.log(err));
}
combined reducer file
import { combineReducers } from "redux";
import words from './words';
export default combineReducers({
words
});
The reducer file word.js
import { GET_WORDS } from '../actions/types';[enter image description here][1]
const initialState = {
words: []
}
export default function (state = initialState, action) {
switch (action.type) {
case GET_WORDS:
return {
...state,
words: action.payload
}
default:
return state;
}
}
The Component in which the words list will be called: Words.js
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { getWords } from "../../../actions/words";
export class Words extends Component {
static propTypes = {
words: PropTypes.array.isRequired,
getWords: PropTypes.func.isRequired
};
componentDidMount() {
this.props.getWords();
}
render() {
return (
<Fragment>
Hi
</Fragment>
)
}
}
const mapStateToProps = state => ({
words: state.words.words
});
export default connect(mapStateToProps, { getWords })(Words);
And finally the App component
import React, { Component, Fragment } from 'react';
import Footer from './Layout/Footer/Footer';
import Header from './Layout/Header/Header';
import WordsDashboard from './Content/Words/WordsDashboard';
import { store } from '../store';
import { Provider } from "react-redux";
import { Words } from './Content/Words/Words';
export class App extends Component {
render() {
return (
<Provider store={store}>
<Fragment>
<Header />
React Buddy
<Words />
<Footer />
</Fragment>
</Provider>
)
}
}
export default App;
Your initialState has only words prop, so when mapping it to props you have one extra words level. Try changing it to:
const mapStateToProps = state => ({
words: state.words
});
Also you need to use mapDispatchToProps for getWords, since in your current code you're missing dispatch wrapper:
const mapDispatchToProps = dispatch => ({
getWords: () => dispatch(getWords())
})
export default connect(mapStateToProps, mapDispatchToProps)(Words);

problems with connecting a child component with the store in react-redux app

am working on react app for the first time and learn about redux. the problem I define a store in App.js and pass it to application using Provider bu when I try to access it to a child component I have an undefined in my console after map it with mapStateToProps. please can you check my code and tell me what am doing wrong?
I create a 2 reducers in folders reducers call index.js and testIt.js after that I import testIt.js in index.js which have a combineReducers to add feature reducers. after i export it for the App.js and Provide the store using the provider of react-redux.
App.js
import React, { Component } from 'react';
import {BrowserRouter , Route} from "react-router-dom";
import { Provider } from 'react-redux';
import Store from "./reducers/index";
import { TestIt } from "./components/TestIt";
import './App.css';
//console.log(Store.getState());
class App extends Component {
render() {
return (
<div className="App">
<Provider store={Store}>
<BrowserRouter>
<Route exact path="/login" component={TestIt} />
</BrowserRouter>
</Provider>
</div>
);
}
}
export default App;
reducers/index.js
import { combineReducers, createStore } from 'redux';
import notes from "./testIt";
const leadApp = combineReducers({
notes
})
export default createStore(leadApp);
reducers/testIt.js
test .js
const initialState = [
{text: "Write code!"}
];
export default function notes(state=initialState, action) {
switch (action.type) {
default:
return state;
}
}
finally my sub-component src/components/TestIt.js
import React, { Component } from 'react';
import {connect} from 'react-redux';
export class TestIt extends Component {
constructor(props){
super(props)
}
render() {
console.log(this.props.notes)
return (
<div>
<h2>Welcome to TestIt!</h2>
<hr />
<h3>Notes</h3>
<table>
<tbody>
{this.props.notes.map(note => (
<tr>
<td>{note.text}</td>
<td><button>edit</button></td>
<td><button>delete</button></td>
</tr>
))}
</tbody>
</table>
</div>
)
}
}
const mapStateToProps = (state) => {
return notes : state.notes
}
// const mapDispatchToProps = dispatch => {
// return {
// }
// }
export default connect(mapStateToProps)(TestIt);
I have now this.props.notes give me undefined of the reducers testIt.j .I suspect something on the store I pass to to the provider does not reach the sub-component even if i do the connection with the method connect(). I expect to access to the testIt.js reducers in my sub component.
Please really need help I try and read to much articles and documentations.
const mapStateToProps = (state) => {
return notes : state.notes
}
not getting the value in state.notes because you are assigning the state in notes.state
Your code:-
switch (action.type) {
default:
return state;
}
so you will get the value in state.notes.state
If you want to change state property then you can change the code:-
export default function notes(state=initialState, action) {
switch (action.type) {
default:
return {data:state};
}
}
sub-component src/components/TestIt.js
const mapStateToProps = (state) => {
return notes : state.notes.data
}
but this is not a good solution because this reducers not having any action type, so it will execute every time.
thanks.
i find a way to resolve my problem
removing export before class in TestIt.js resolve it.

Could not find "store" in either the context or props of "Connect(App)". I have a <Provider> wrapping the component already

Invariant Violation: Could not find "store" in either the context or props of "Connect(App)". Either wrap the root component in a , or explicitly pass "store" as a prop to "Connect(App)".
I hate to ask a variation of a question that has been asked many times, but I have tried all the proposed solutions with no luck.
https://codesandbox.io/s/0pyl7n315w
index.js
import React, {Component} from 'react'
import {AppRegistry} from 'react-native'
import {Provider} from 'react-redux'
import App from './app'
import configureStore from './store.js'
const store = configureStore();
class MyCounterApp extends Component {
render() {
return(
<Provider store={store}>
<App/>
</Provider>
)
}
}
AppRegistry.registerComponent('MyCounterApp', () => MyCounterApp)
app.js
import React from 'react';
import {Button, Text, View} from 'react-native';
import {addToCounter} from "./actions";
import { connect } from 'react-redux';
class App extends React.Component {
handleOnClick = event => {
this.props.addToCounter()
};
render() {
return (
<View>
<Text>{this.props.count}</Text>
<Button onPress={() => this.props.addToCounter()}
title={"Click Me!"}>
</Button>
</View>
)
}
}
function mapDispatchToProps(dispatch) {
return {
addToCounter: () => dispatch(addToCounter())
}
}
function mapStateToProps(state) {
return {
count: state.count
}
}
export default connect(mapStateToProps, mapDispatchToProps)(App)
store.js
import reducer from './reducer'
import {createStore} from 'redux'
export default function configureStore() {
let store = createStore(
reducer
)
return store
}
reducer.js
import {ADD_TO_COUNTER} from './actions'
const initialState = {
counter: 0
}
const reducer = (state = initialState, action) => {
switch (action.type) {
case ADD_TO_COUNTER:
return {
...state,
counter: state.counter + 1
}
default:
return state
}
}
export default reducer;
I am following along with this tutorial:
https://medium.com/#pavsidhu/using-redux-with-react-native-9d07381507fe
If you want to test components without using store, the first thing you have to do is export your disconnected component like: export { Component }.
Then you'll have to import on your test file like that: import { Component } from ...
If the error persists, look to see if the component uses components that are connected, and if yes, you have to mock that one, for example:
jest.mock('../../../AnotherComponent', () => ChildComponent => props => <ChildComponent {...props} />);
Example:
const Component = (props: Props) => (
<>
...
<AnotherComponent // connected component inside <Component />
{...props}
/>
</>
)
const mapStateToProps = (state: State) => ({});
const mapDispatchToProps = {
export default connect(
mapStateToProps,
mapDispatchToProps
)(Component);
export { Component }; // disconnected component
You have not provided store to your App component. that's why it is failed to connect component with reducer:
class MyCounterApp extends Component {
render() {
return(
<Provider store={store}>
<App/>
</Provider>
)
}
}
Remove provider from app.js

Why isn't my state correctly mapped to props in Redux?

I created this component:
import React, { Component } from 'react';
import { connect } from 'react-redux';
export class Todos extends Component {
render() {
//todo remove
console.log('testing this.props.todos', this.props.todos);
//todo remove
debugger;
return (
<div>hello from todos</div>
);
}
}
const mapStateToProps = function (store) {
return {
todos: store.todos
}
}
export default connect(mapStateToProps)(Todos)
I am using Redux and this is the reducer:
const initialState = {
todos: [
{
name:'first todo'
}
]
}
const Todos = (state = initialState, action) => {
switch (action.type) {
case "ADD_TODO":
var newState = Object.assign({}, state, {todos: [...state.todos, action.data]});
return newState;
default:
//todo remove
debugger;
return state;
}
}
export default Todos;
For some reason the this.props.todos is undefined and my state is not mapped to my props correctly. How can I hook up the Redux store to my component?
The problem is that you're not passing the store correctly down to your components! If you want to use connect to connect your component to the global state, you have to use the <Provider> component provided by react-redux. So, first you create your store with createStore as you've done, then pass it into the provider:
import store from './store.js';
import { Provider } from 'react-redux';
const App = () => (
<Provider store={store}>
<Todos />
</Provider>
);
ReactDOM.render(
<div className="container">
<App />
</div>
, document.getElementById('root'));
Notice how the <Provider> is used to provide the store and make it available for your connect calls. Also, <Todos> shouldn't take any props. Also, your import:
import { Todos } from './components/todos.jsx';
Is wrong. Your todos.jsx, you're exporting the connected component like this, as the default export:
export default connect(mapStateToProps)(Todos)
So you have to import the default instead:
import Todos from './components/todos.jsx';

Resources