React Native - Redux - reactjs

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

Related

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

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);

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.

React component not getting latest redux state values

I'm having an issue with a React Native application that uses Redux, and I've struggling to figure out the cause.
When the Redux state is changed by a dispatch in component A, component B doesn't show the most up to date value of the Redux state. For example, say I click a button in component A to change a Redux value from 0 to 1, it will show 0 in component B, but when I click the button to add 1 to make it 2, component B will show 1. Below is an example of my code. When I click on the TouchableOpacity in component A, it should change this.props.screen from 1 (the initial state) to 0. In component B, I have a regular console.log of this.props.screen, and a console.log inside a setTimeout with 50 milliseconds. Inside the console, the console.log in the setTimeout has the correct value of 0 when hit, however the one outside it still shows 1. Similarly, the text rendered in component B will show 1 as well. If I click the button again, it will then show 0.
I've included the relevant action and reducer from my code. At first, I thought it might be a mutation, but it seemed that can only happen with objects and arrays (I'm only using a number). I would appreciate some help figuring out how to have the text rendered in component B reflect the most current value. Thanks in advance!
Component A
import { connect } from "react-redux";
import { setScreen } from "../redux/Actions";
class Header extends Component {
componentWillReceiveProps(nextProps){
setTimeout(() => { this.logoHide() },10);
this.props.scrollLocation < 10 ? this.changeTransparency(0) : this.changeTransparency(.9);
}
setScreen(screen){
this.props.setScreen(screen);
}
render() {
var {height, width} = Dimensions.get('window');
return (
<View>
<TouchableOpacity onPress={() => this.setScreen(0)}>
<Text>Click Me</Text>
</TouchableOpacity>
</View>
);
}
}
const mapStateToProps = state => {
return {
height: state.height,
platform: state.platform,
screen: state.screen,
scrollLocation: state.scrollLocation
};
};
const mapDispatchToProps = dispatch => {
return {
setScreen: (value) => dispatch(setScreen(value))
};
};
export default connect(mapStateToProps,mapDispatchToProps)(Header);
Redux Action
import { SET_SCREEN } from './Constants';
export const setScreenDispatcher = (value) => ({ type: SET_SCREEN, screen: value});
export const setScreen = (value) => {
return (dispatch) => {
dispatch(setScreenDispatcher(value));
}
}
Redux Reducer
import { combineReducers } from 'redux';
import { SET_SCREEN } from "./Constants";
const initialState = []
const screen = (state = 1, action) => {
switch (action.type) {
case SET_SCREEN:
return action.screen;
default:
return state;
}
};
// COMBINE REDUCERS //
export default combineReducers({
screen
});
Component B
import { connect } from "react-redux";
class VisibleMenus extends Component {
componentWillUpdate(){
console.log(this.props.screen);
setTimeout(() => {console.log(this.props.screen)},50);
}
}
render() {
return (
<View>
<Text>{this.props.screen}</Text>
</View>
);
}
}
const mapStateToProps = state => {
return {
screen: state.screen
};
};
const mapDispatchToProps = dispatch => {
return {
};
};
export default connect(mapStateToProps,mapDispatchToProps)(VisibleMenus);
App.js
import React, {Component} from 'react';
import { Provider } from "react-redux";
import VisibleMenus from './VisibleMenus';
import { Store } from "./redux/Store";
const store = Store();
export default class App extends Component {
render() {
return (
<Provider store={store}>
<VisibleMenus />
</Provider>
);
}
}
Store.js
// REDUX STORE //
import { createStore, applyMiddleware } from "redux";
import rootReducer from "./Reducers";
import ReduxThunk from 'redux-thunk'
export const Store = (initialState) => {
return createStore(
rootReducer,
initialState,
applyMiddleware(ReduxThunk)
);
}
For anyone who runs into this, I thought I'd share how I fixed it.
I researched mutations, and I definitely wasn't mutating the state, yet my components would not update when the Redux store changed.
I tried using both componentWillUpdate() and componentWillReceiveProps() but both didn't change anything. However, I was doing a comparison between this.props.screen and this.state.screen which ended up being my issue.
I should have been doing a comparison with nextProps.screen and this.state.screen inside a componentWillReceiveProps(nextProps) which ended up fixing everything.
I do want to thank Hashith for his help.

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

cant access to store in redux app

i want to use redux in my react native app
and i make my reducer correctly (i think ) and after that create store and then use dispatch or store but i get error actually i cant use dispatch
my app.js:
const store = createStore(rootReducer, applyMiddleware(logger));
export default class taav extends Component {
render() {
return (
<Provider store={store}>
<Chatroom />
</Provider>
);
}
}
and my chatroom :
import React, {Component} from 'react';
import {Text, Button, TabBarIOS, View} from 'react-native'
import MessageList from './messageList'
import {connect} from 'react-redux'
const mapStateToProps = (state) => {
return {
testtest: state.chatroom.teststore.test
}
}
export const Testredux = connect(mapStateToProps)(MessageList)
export default class Chatroom extends Component {
state = {
test2: "dfsd"
}
componentDidMount() {
console.log('this')
}
btn() {
dispatch({type: 'test1'})////////////this is wrong???
}
render() {
return (
<View>
<Testredux test={'sdfdsf'}/>
<Button title={'sdfsdf'} onPress={this.btn.bind(this)}/>
</View> )
}
}
do you know why i cant use dispatch????
You have not imported the 'dispatch' function anywhere so that's why you can't use it. You would have to import your store and then call store.dispatch().
However, the best (and recommended) way would be to use mapDispatchToProps with the connect function from react-redux when you export your Chatroom component:
function mapDispatchToProps(dispatch) {
return({
sendTestAction: () => { dispatch({type: 'test1'}) }
})
}
...and then use it with connect like this when you export your component:
connect(mapStateToProps, mapDispatchToProps)(Chatroom)
In your Chatroom component you can then do:
render() {
return (
<View>
<Testredux test={ 'sdfdsf' }/>
<Button title={ 'sdfsdf' } onPress={ this.props.sendTestAction }/>
</View>
)
}
I hope this helps.
You're connecting the wrong class
export const Testredux = connect(mapStateToProps)(MessageList)
should be
export const Testredux = connect(mapStateToProps)(Chatroom)
dispatch is a prop passed to the component wrapped in the connect call. Since you're wrapping MessageList instead of Chatroom, instances of Chatroom cannot access any props passed by Redux.
Additionally, dispatch should be accessed as a prop, so it should be this.props.dispatch instead of just dispatch:
btn() {
this.props.dispatch({type: 'test1'})
}

Resources