Props.store does not work on child components - reactjs

please help.
this.props.store does not work on child components.
but the connect(mapStateToProps, mapDispatchToProps) ... is working fine.
why doesn't work only child components?
1. parent code (is working fine)
import React from 'react';
import ReactDOM from 'react-dom';
import { Home } from './container/home/index';
import { ChildrenComponent } from './container/childrenComponent';
import { Match, Miss } from 'react-router';
import { BrowserRouter as Router } from 'react-router';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import Reducers from './reducers';
const store = createStore(Reducers);
store.subscribe(() => console.log('ㅡㅡㅡㅡㅡ store was updated ㅡㅡㅡㅡㅡ'));
store.subscribe(() => console.log(store.getState()));
store.subscribe(() => console.log('ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ'));
ReactDOM.render(
<Provider store={store}>
<Router>
<div>
<Match pattern="/" component={Home} />
<Match pattern="/ChildrenComponent" component={ChildrenComponent} />
</div>
</Router>
</Provider>,
document.getElementById('root')
);
2. Children Component (is not working only 'this.props.store ..... ')
import React, { Component } from 'react';
import $ from 'jquery';
import { connect } from 'react-redux';
class ChildrenComponent extends Component {
constructor (props) {
super (props);
}
render (
console.log(this.props.store) // undfined
console.log(this.props.store.getState()) // does not working
const mapStateToProps = (state) => {
return {
// .... is working fine
}
}
const mapDispatchToProps = (dispatch) => {
return {
// .... is working fine
}
}
)
return (
<divHellow world</div>
)
}
expoert default connect(mapStateToProps, mapDispatchToProps)(ChildrenComponent);

Trying to access the store and its state directly defeats the entire purpose of using Redux, and React-Redux in particular. You're supposed to use mapStateToProps to access parts of state that you need in each particular component.

Put mapStateToProps and mapDispatchToProps outside the component class and put your jsx inside the render method of your component class.
class ChildrenComponent extends Component {
render () {
return (
<divHellow world</div>
)
}
}
const mapStateToProps = (state) => {
return {
// ....
}
}
const mapDispatchToProps = (dispatch) => {
return {
// ....
}
}
export default connect(mapStateToProps, mapDispatchToProps)(ChildrenComponent);

Related

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

mapStateToProps() in Connect(EquipmentMetadata) must return a plain object. Instead received undefined

I am getting the following errors when running my code and am not sure where to start with debugging this.
mapStateToProps() in Connect(EquipmentMetadata) must return a plain
object. Instead received undefined. Warning: Failed prop type: The
prop name is marked as required in EquipmentMetadata, but its value is
undefined.
This is the index file :
import 'babel-polyfill'
import React from 'react'
import { render } from 'react-dom'
// import Root from './containers/Root'
import { setName } from './actions'
// import createStore from './common/store/'
import { Provider } from 'react-redux'
import EquipmentMetadata from './containers/EquipmentMetadata'
// import ReduxPiece from './components/ReduxPiece'
import configureStore from './configureStore'
const store = configureStore()
window.EquipmentMetadata = {
store,
setName
}
render(
<Provider store={store}>
{/* <Root /> */}
<EquipmentMetadata />
</Provider>,
document.getElementById('equipment-metadata')
)
equipmentmetadata.js:
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import Greeting from '../components/Greeting'
// import ReduxPiece from "../components/ReduxPiece";
class EquipmentMetadata extends Component {
render () {
// const { name } = this.props
return (
<div>
<Greeting
// name={name}
/>
{/* <ReduxPiece /> */}
</div>
)
}
}
EquipmentMetadata.propTypes = {
name: PropTypes.string.isRequired
}
function mapStateToProps (state) {
// const { name } = state
// return {
// name
// }
}
function mapDispatchToProps (dispatch) {
return {}
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(EquipmentMetadata)
It is telling you that mapStateToProps should be returning something - you've commented all of it entirely. If you don't want it to return anything then just make it return {}. Also, in commenting it out, your EquipmentMetadata says in its propTypes that it requires a name prop, which you now aren't sending it.
mapStateToProps needs to be a function which returns an object. The notation of the mapStateToProps function can be as given below.
//ES5
function mapStateToProps (state) {
return {
key: name of the reducer function
}
}
//ES6
const mapStateToProps = (state) => ({
key: name of the reducer function
})
For your code you can try by making the changes like
function mapStateToProps (state) {
return {
name: state.nameOfReducer.valueinReducer
}
}

Connected component not receiving store props n Redux

I was doing a bit of refactoring and tried connecting a higher level component to redux using connect() but the component I'm connecting keeps giving me empty props.
I've included the relevant code, I've structured my redux reducers into a ducks format, so the actions/creators and reducers are in one module file.
The files are containers/login.js, presentation/login.js, presentation/logins.js, app.js and the root index.js.
When I decided to rename some actions, files and reducers, moved the connect to a higher component, the connection stopped working and now I have empty props.
Help much appreciated.
// containers/login.js
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom'
import { fetchPage } from '../redux/modules/Login';
import Login from '../presentation/Login';
const mapStateToProps = (state) => {
return {
page: state.page,
forms: state.forms
}
}
const mapDispatchToProps = (dispatch) => {
return {
fetchPage: () => dispatch(fetchPage())
} // here we're mapping actions to props
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(Login);
// redux/modules/login.js
import fetch from 'cross-fetch';
const RECIEVE_FORM = 'RECIEVE_FORM';
export const receiveForm = (response) => ({
type: RECIEVE_FORM,
forms: response.forms
})
const initialState = {
page: "",
forms: []
}
// MIDDLEWARE NETWORK REQUEST DISPATCHER
export const fetchPage = () => {
return dispatch => {
return fetch('http://localhost:3001/login')
.then(
response => response.json(),
)
.then(
response => dispatch(receiveForm(response))
)
}
}
// REDUCER COMPOSITION CALL EXISTING REDUCERS
// REDUCER COMPOSITION PATTERN
// ACCUMULATIVE ACTION REDUCER
export default function Login(state = initialState, action){
switch (action.type){
case RECIEVE_FORM:
return {
...state,
forms: action.forms
}
default:
return state;
}
}
// presentation/login.js
import React, { Component } from 'react';
import styled from 'styled-components';
import Wrapper from '../components/Wrapper';
import Card from '../components/Card';
import Text from '../components/Text';
import Logo from '../components/Logo';
import FormGroup from '../components/FormGroup';
const WrapperLogin = styled(Wrapper)`
.login__card{
padding: 4.5rem 2.5rem 2rem 2.5rem;
}
`;
const BoxLogo = styled.div`
.login__logo{
display: block;
margin: 0 auto;
}
`;
export default class Login extends Component{
componentDidMount() {
console.log(this.props)
//this.props.fetchPage();
}
render(){
return(
<main>
<WrapperLogin className="login">
<Card className="login__card">
<BoxLogo>
<Logo className="login__logo" width={187.36} height={76.77} />
</BoxLogo>
<FormGroup name="login" className="login_formGroup" />
</Card>
<Text primitive="p" margin='4px 0 0 0' size="0.8rem" textAlign="center" display='block'>Brought to you by WORLDCHEFS</Text>
</WrapperLogin>
</main>
)
}
}
// app.js
// manage routes here
//import _ from 'lodash';
import React, { Component } from 'react'
import { BrowserRouter as Router, Route, Redirect } from 'react-router-dom';
import { ThemeProvider } from 'styled-components';
import Login from './presentation/Login';
type Props = {
}
type State = {
mode: string
};
export default class App extends Component <Props, State> {
constructor(){
super();
this.state = {
...this.state,
mode: 'mobile'
}
}
render(){
return(
<ThemeProvider theme={{ mode: this.state.mode }}>
<Login />
</ThemeProvider>
)
}
}
// root
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import configureStore from './redux/configureStore';
import registerServiceWorker from './registerServiceWorker';
import App from './App';
import { injectGlobal } from 'styled-components';
import styles from './assets/styles';
const store = configureStore();
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>
, document.getElementById('root')
);
The reason your props in Login component are empty is because you are not actually using the connected Login container, As you have mentions its in containers/login
So in your App.js change the import of login from ./presentation/login to
import Login from '/path/to/containers/Login';
You have imported presentation component in your app.js rather than container component. Please import your container component like below
import Login from './containers/login.js';
This will solve the problem as per my understanding from your code

Where to set the visibility of Network Indicator with Redux?

I have several actions in my application which fetches data from an API. I am setting a "loading"-attribute in my redux-store, if the action is fetching. Now I want to show a network indicator the app is fetching data.
I found a quick&dirty solution but I am sure, that this is not the way to do it:
import React, { Component } from 'react';
import { AppRegistry, StatusBar } from 'react-native';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import reducer from './app/reducers';
import App from './app/providers/App';
const createStoreWithMiddleware = applyMiddleware(thunk)(createStore);
const store = createStoreWithMiddleware(reducer);
class AppName extends Component {
render() {
store.subscribe(() => {
if(
store.getState().dishes.loading
|| store.getState().deals.loading
) StatusBar.setNetworkActivityIndicatorVisible(true);
else StatusBar.setNetworkActivityIndicatorVisible(false);
});
return (
<Provider store={store}>
<App />
</Provider>
);
}
}
AppRegistry.registerComponent('AppName', () => AppName);
What is the correct way to hook such a listener?
To avoid calling StatusBar.setNetworkActivityIndicatorVisible too many times, you can watch the changes in your state using componentWillReceiveProps in your connected component.
import AppContainer from './containers/AppContainer';
class AppName extends Component {
render() {
return (
<Provider store={store}>
<AppContainer />
</Provider>
);
}
}
containers/AppContainer.js
import App from '../components/App.js';
const mapStateToProps = state => ({
loading: state.dishes.loading || state.deals.loading
});
export default connect(mapStateToProps)(App);
components/App.js
class App extends Component {
componentWillReceiveProps(nextProps) {
if (!this.props.loading && nextProps.loading) {
// Changing from `not loading` to `loading`
StatusBar.setNetworkActivityIndicatorVisible(true);
} else if (this.props.loading && !nextProps.loading) {
// Changing from `loading` to `not loading`
StatusBar.setNetworkActivityIndicatorVisible(false);
}
}
// ...
}

Resources