I have a parent component that I want to be tabs for multiple children. For some reason, my child component has more props data than the parent.
Parent component
import React, { Component} from 'react';
import { Link } from 'react-router';
import { connect } from 'react-redux';
class TerritoryTabs extends Component {
componentWillMount() {
console.log('this is the parent props (tabs)')
console.log(this.props);
}
render() {
return (
{this.props.children}
);
}
}
export default connect(null, null)(TerritoryTabs);
Child component
import React, { Component} from 'react';
import { Link } from 'react-router';
import { connect } from 'react-redux';
import { reduxForm } from 'redux-form';
import { getTerritoryGeographies } from '../actions/index';
import TerritoryTabs from './territory-tabs';
class TerritoryGeographyList extends Component {
componentWillMount() {
console.log('this is child props (TerritoryGeographyList)');
console.log(this.props);
this.props.getTerritoryGeographies(this.props.params.id);
}
render() {
return (
<TerritoryTabs>
<div>This list goes here</div>
</TerritoryTabs>
);
}
}
function mapStateToProps(state) {
return { territoryGeographies: state.territoryGeographies.all
};
}
export default connect(mapStateToProps, { getTerritoryGeographies })(TerritoryGeographyList);
Here is what the console prints.
The wrap component should be called "parent". Example:
<Parent>
<Child />
</Parent>
So, in your case, fix this line:
class TerritoryTabs extends Component {
componentWillMount() {
console.log('this is the child props (tabs)') // <-- Fix this line, it should be the "child"
console.log(this.props);
}
and this line:
class TerritoryGeographyList extends Component {
componentWillMount() {
console.log('this is parent props (TerritoryGeographyList)'); // <-- fix this line, it should be "parent"
console.log(this.props);
this.props.getTerritoryGeographies(this.props.params.id);
}
Related
I've got a parent component Course that is able to get state from redux and I'm able to log that out successfully:
import React, { Component } from "react";
import { connect } from "react-redux";
import SchoolWrapper from "../SchoolWrapper";
export class Course extends Component {
constructor(props) {
super(props);
console.log("Props in course", props);
}
render() {
return (
<>
<SchoolWrapper>Wrapped component</SchoolWrapper>
</>
);
}
}
const mapStateToProps = (state) => ({
user: state.user,
});
export default connect(mapStateToProps)(Course);
Nested in the Course component is another component SchoolWrapper that is able to get props from redux state:
import React, { Component } from "react";
import { connect } from "react-redux";
import { Nav } from "./Student/Nav";
export class SchoolWrapper extends Component {
constructor(props) {
super(props);
console.log("SchoolWrapper props", props);
}
render() {
return (
<>
<Nav />
</>
);
}
}
const mapStateToProps = (state) => ({
user: state.user,
});
export default connect(mapStateToProps)(SchoolWrapper);
However, the Nav component or any other component nested at this level is not able to access state from redux.
import React, { Component } from "react";
import { connect } from "react-redux";
export class Nav extends Component {
constructor(props) {
super(props);
console.log("Nav props: ", props);
}
render() {
return (
<div>
nav goes here...
</div>
);
}
}
const mapStateToProps = (state) => ({
user: state.user,
});
export default connect(mapStateToProps)(Nav);
Where am I going wrong?
I think you're importing Nav wrong, here you're using a "default" export:
export default connect(mapStateToProps)(Nav);
But you try to use a "named" import:
import { Nav } from "./Student/Nav";
Nav should be imported as a "default":
import Nav from "./Student/Nav"
How to pass an Array from Child component to Parent Component in react
this is my code
This is my Parent component
import React, { Component } from 'react';
import Child from '../Child/Child';
export default class Parent extends Component {
render() {
return (
<div>
<Child></Child>
</div>
)
}
}
This is Child component
import React, { Component } from 'react'
export default class Child extends Component {
render() {
const students = ['Mark','John'];
return (
<div>
</div>
)
}
}
Use React Components States and Props to achieve this:
Parent:
import React, { Component } from 'react';
import Child from '../Child/Child';
export default class Parent extends Component {
constructor(props) {
super(props);
this.state = {data: []} // Initialize the State
this.onChildData = this.onChildData.bind(this); // Bind the helper method
}
/*
* This method is just to update the state with new data incoming from Child
* You can even inline this in your 'render' method
*/
onChildData(data) {
this.setState({data});
}
render() {
return (
<div>
/*
* Add a 'onData' prop to invoke from Child
* It will work as a callback
*/
<Child onData={this.onChildData}></Child>
</div>
)
}
}
Child:
import React, { Component } from 'react'
const students = ['Mark','John'];
export default class Child extends Component {
/**
* componentDidMount is called by React immediately after this component is mounted
* We use it to call the 'onData' callback and send data to the parent
*/
componentDidMount() {
this.props.onData(students);
}
render() {
return (
<div>
</div>
)
}
}
I'm really regarding props in React/React-Native. I have a parent view. In this view I'm getting the user data from a LocalStorage.['
import React, { Component } from 'react';
import { Container, Content, View } from 'native-base';
import NutrionalToolbar from '../../components/NutrionalToolbar';
import { AsyncStorage } from 'react-native';
export default class LogsScreen extends Component {
state = {
user: '',
}
componentWillMount() {
this._bootstrapAsync();
}
_bootstrapAsync = async () => {
const user = await AsyncStorage.getItem('user');
this.setState({ user: JSON.parse(user) })
};
render() {
return (
<Container>
<NutrionalToolbar user={this.state.user} />
</Container>
);
}
}
Now inside the NutrionalToolbar component I have this.
import React, { Component } from 'react';
import { View } from 'native-base';
class NutrionalToolbar extends Component {
constructor(props) {
super(props)
console.log(this.props) // This renders an empty user object
}
render() {
console.log(this.props) // This renders the user object with values
return (
<View>
</View>
);
}
}
export default NutrionalToolbar;
How can I get this.props values inside the constructor. I'm getting the values inside render method. Why isn't working inside the constructor?
I would recommend looking into the componentDidUpdate lifecycle hook because, even if you could access the initial user prop in the constructor, you wouldn't be able to access updates to that prop in the constructor.
import React, { Component } from 'react';
import { View } from 'native-base';
class NutrionalToolbar extends Component {
componentDidUpdate() {
console.log(this.props) // This will always log the current props
}
render() {
return (<View></View>);
}
}
export default NutrionalToolbar;
I have a container which has access to the Redux state and maps a certain pieces of that state to its props, the piece I'm interested in is 'coins' so
this.props.coins
Using console.log() I can see that when rendering the container I have access to that piece of state.
This container houses one component that receives a callback function and this previously mentioned piece of state, coins, via its own props in
onClickHandler() && coinData
The container has a function to handle the callback called
_handleClick()
In this function for some reason this.props doesn't give access to the same coins I was able to access in the render function but has access to the props that I'm passing to the component, props I thought would belong to the component. So from _handleClick() in the container I have access to
this.props.onClickHandler() && this.props.coinData
but not
this.props.coins
which is what I was expecting to have access to from anywhere within my container. I get the error in the title of the post when I try to access this.props.coins in my callback handler _handleClick() but why is that and why do I have access to the props that should belong to the corresponding child component? Is there any way that I can access this.props.coins from the _handleClick() call?
My container:
import React, { Component } from 'react';
import '../App.css';
import { connect } from "react-redux";
import ChartSelectMenu from '../components/ChartSelectMenu';
import { selectCoinForChart } from '../actions/index';
class ChartSelectMenuContainer extends Component {
constructor(props) {
super(props);
}
_handleClick(ticker) {
//event.preventDefault();
console.log("Clicked: ", ticker);
console.log("coin_list: ", this.props);
const coin_list = this.props.coins;
//
for (let i=0; i<coin_list.length; i++) {
if (coin_list[i].ticker === ticker) {
this.props.dispatch(selectCoinForChart(ticker));
}
}
}
render() {
console.log("Container props on render(): ", this.props);
return (
<ChartSelectMenu
onClickHandler={this._handleClick}
coinData={this.props.coins}
/>
);
}
}
function mapStateToProps({ auth, coins, selectedCoin }) {
return { auth, coins, selectedCoin };
}
export default connect(mapStateToProps)(ChartSelectMenuContainer);
It's component:
import React, {Component} from 'react';
import Paper from 'material-ui/Paper';
import Menu from 'material-ui/Menu';
import MenuItem from 'material-ui/MenuItem';
const style = {
display: 'inline-block',
margin: '16px 0px 16px 0px',
};
class ChartSelectMenu extends Component {
constructor(props) {
super(props);
}
_renderMenuItems() {
if (this.props === null) {
return <h3>Loading...</h3>;
} else {
return(this.props.coinData.map((coin) => {
return <MenuItem
key={coin.ticker}
onClick={this.props.onClickHandler.bind(this, coin.ticker)}
primaryText={coin.ticker}
/>
}));
}
}
render() {
//console.log('ChartSelectMenu props: ', this.props);
return (
<div>
<Paper style={style}>
<Menu>
<ul>
{this._renderMenuItems()}
</ul>
</Menu>
</Paper>
</div>
)
}
}
export default ChartSelectMenu;
When #MukulSharma commented 'use var self = this inside your function' I thought to try to bind the _handleClick function in the constructor of the container and it worked.
The solution:
import React, { Component } from 'react';
import '../App.css';
import { connect } from "react-redux";
import ChartSelectMenu from '../components/ChartSelectMenu';
import { selectCoinForChart } from '../actions/index';
class ChartSelectMenuContainer extends Component {
constructor(props) {
super(props);
this._handleClick = this._handleClick.bind(this);
}
_handleClick(ticker) {
//event.preventDefault();
console.log("Clicked: ", ticker);
console.log("coin_list: ", this.props);
const coin_list = this.props.coins;
//
for (let i=0; i<coin_list.length; i++) {
if (coin_list[i].ticker === ticker) {
this.props.dispatch(selectCoinForChart(ticker));
}
}
}
render() { ...
I have the following parent component:
import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux';
import {bindActionCreators} from 'redux';
import _ from "lodash";
import ChildComponent from "./ChildComponent";
class ParentComponent extends Component {
constructor(props) {
super(props);
this.state = {
};
}
render() {
return (
<div>
I'm at Parent
<ChildComponent/>
</div>
);
}
}
function mapStateToProps(state) {
return { }
}
export default connect(mapStateToProps, null)(ParentComponent);
Inside the parent has a component called ChildComponent that looks like this:
import React, { Component, PropTypes } from "react";
import { connect } from "react-redux";
import { reduxForm } from "redux-form";
import { bindActionCreators } from "redux";
class ChildComponent extends Component {
constructor(props) {
super(props);
}
componentWillMount() {
}
render() {
return (
<div>
at the child
</div>
);
}
}
function mapDispatchToProps(dispatch) {
return bindActionCreators(
{
},
dispatch
);
}
function mapStateToProps(state) {
return {
};
}
export default connect(mapStateToProps, mapDispatchToProps)(
ChildComponent
);
When I try adding the child component I keep getting this error:
But if I click continue the page turns back to normal. I don't understand how the child component is undefined. It's just embedded and does not include any props.
UPDATE:
I'm not getting the error anymore but I notice my page turns blank when I open this particular component. I'll be doing a bit more troubleshooting.
I tried out your code, and it works fine for me. My thought was maybe what your entry file looks like? or file structure? If you like you can try the following syntax for the parent and child - it worked this way as well:
Child:
const mapStateToProps = () => {
return {}
}
const ConnectedChildComponent = connect(
mapStateToProps,
{})(ChildComponent)
export default ConnectedChildComponent;
Parent:
const mapStateToProps = () => {
return {}
}
const ConnectedParentComponent = connect(
mapStateToProps,
{})(ParentComponent)
export default ConnectedParentComponent;
In your ParentComponent change:
import ChildComponent from "./ChildComponent";
to
import ChildComponent from "./ChildComponent.jsx";
i.e. add the missing ".jsx" extension. Your code is most likely determining the import to be a ".js" file by default, whereas it's actually a ".jsx" file.