I am trying to pass some states between components however the values are always undefined.
I have a component called Home. When the user types in their email and password to login I want to pass those states to my other component i.e. So I have the users login information. However, the console.log statements show they are undefined.
Home.js in render method
return (
<div>
<HomePage signInEmail={this.state.signInEmail} signInPassword={this.state.signInPassword}/>
<p>Account</p>
<button onClick={this.logout}>Logout</button>
</div>
);
Below is what I have tried for HomePage.js
constructor(props) {
super(props);
this.state = {
noResp: ''
}
}
componentDidMount() {
console.log('Component Mounted!');
console.log('this.props.signInEmail ' + this.props.signInEmail );
console.log('this.props.signInPassword: ' + this.props.signInPassword);
}
The above comes to undefined. In my Home.js, I can get the values I need but I can't seem to pass these to a different component.
You can access it by
this.props.signInEmail
this.props.signInPassword
in your HomePage.js.
When you want to pass some data from parent to child component, they are called props.
Perhaps this help! State and Props in React
You can recieve props from parent component by writing
class HomePage extends React.Component{
constructor(props){
super(props);
}
render(){
return(//THE JSX you wanna return)
}
}
in the child component i.e., HomePage.js in your case!
Related
I am working on an application where I pass variable values in a Navlink using state from one component to the other and then load those received values in input fields and click on submit button in that other component to do something with values. My values are received correctly and show up correctly when I alert them. But when I click submit button, it gives error,pointing at the constructor
TypeError: Cannot read property 'id' of undefined
Here is my code
class Parent extends React.Component{
constructor(props) {
super(props);
this.state={id:2}
}
render(){
return(
<NavLink
to={{
pathname: '/Child',
state: {
id: this.state.id
}
}}
>
Edit
</NavLink>
)
)
}
Where I receive the values
class Child extends React.Component{
constructor(props) {
super(props);
this.state = {id:this.props.location.state.id}
alert(this.props.location.state.id)//works fine
}
setId(e){
this.setState({id:e.target.value})
}
addOrEdit(){ //gives error
alert(this.state.id)
//do something
}
render(){
return(
<div>
<form>
<label>Id</label>
<input value={this.state.id} onChange={this.setId.bind(this)} type="text"/><br/>
<input type="submit" onClick={this.addOrEdit.bind(this)} ></input>
</form>
</div>
)
}
}
this.state = {id: this.props.location && this.props.location.state && this.props.location.state.id}
Should fix your issue that caused by times that this component called without this context or this line got excuted before location set.
(assuming you using withRouter for making location props be exist...)
Anyhow, and not related directly to your issue, it is bad practice to set initial value for state from props at constructor, consider manipulate state through life cycle either don't use state here and refer to props directly
I would suggest to just use arrow functions for setId and addOrEdit.
addOrEdit = (e) => {
// ...
}
And just call them:
onChange={this.setId}
onClick={this.addOrEdit}
https://medium.com/#machnicki/handle-events-in-react-with-arrow-functions-ede88184bbb
Also you are deriving state from prop.
It is better to just use the prop directly.
https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html
I am not really sure how to properly ask this question but I will explain what I'm trying to do here:
So I have this parent Component which creates a Component like so:
<CurrentTemperature cityName={this.state.cityName}></CurrentTemperature>
The CurrentTemperature Component looks like this:
import React, { Component } from "react";
import "../App.css";
export default class CurrentTemperature extends Component {
constructor(props) {
super(props);
this.state = {
temperature: 0,
cityName: this.props.cityName,
};
}
componentDidMount() {
//fetch the temperature from api here
}
render() {
return (
<div>
<div className="city-temperature">
{this.state.cityName} {this.state.temperature}
</div>
</div>
);
}
}
All I'm trying to do is read the city name from the parent, then fetch the current temperature from my API, and then display both of those in the Component. But if I try to console.log(this.props.cityName) from anywhere other than from inside the city-temperature div, I always get an empty string. What is going on here?
cityName is the state of the parent component. I guess the parent component would get the "cityName" asynchronously. right? If this is the case, You have to put the temperature in the parent component as its state. And you have to insert the API call in the parent component. CurrentTemperature component will behave like a pure function component.
const CurrentTemperature = ({temperature, cityName}) => {
return (
<div className="city-temperature">
{cityName} {temperature}
</div>
);
}
I guess this is not only the solution but also the best DX.
You can remove this in your constructor, and then use this.state.cityName
constructor(props) {
super(props);
this.state = {
temperature: 0,
cityName: props.cityName,
};
}
How to initialize state with dynamic key based on props? The props is a data fetched from external source (async). So the props will change when the data is succesfully downloaded. Consider a component like this.
edit: I want to make the state dynamic because I want to generate a dialog (pop up) based on the item that is clicked. the DialogContainer is basically that. visible prop will make that dialog visible, while onHide prop will hide that dialog. I use react-md library.
class SomeComponent extends React.Component {
constructor() {
super();
this.state = {};
// the key and value will be dynamically generated, with a loop on the props
// something like:
for (const item of this.props.data) {
this.state[`dialog-visible-${this.props.item.id}`] = false}
}
}
show(id) {
this.setState({ [`dialog-visible-${id}`]: true });
}
hide(id) {
this.setState({ [`dialog-visible-${id}`]: false });
}
render() {
return (
<div>
{this.props.data.map((item) => {
return (
<div>
<div key={item.id} onClick={this.show(item.id)}>
<h2> Show Dialog on item-{item.id}</h2>
</div>
<DialogContainer
visible={this.state[`dialog-visible-${item.id}`]}
onHide={this.hide(item.id)}
>
<div>
<h1> A Dialog that will pop up </h1>
</div>
</DialogContainer>
</div>
);
})}
</div>
)
}
}
// the data is fetched by other component.
class OtherComponent extends React.Component {
componentDidMount() {
// fetchData come from redux container (mapDispatchToProps)
this.props.fetchData('https://someUrlToFetchJSONData/')
}
}
The data then is shared via Redux.
However, based on my understanding so far, state can be updated based on props with componentWillReceiveProps or the new getDerivedStateFromProps (not on the constructor as above). But, how to do that on either method?
The example here only explains when the state is initialized on the constructor, and call setState on either cWRP or gDSFP. But, I want the key value pair to be initialized dynamically.
Any help/hint will be greatly appreciated. Please do tell if my question is not clear enough.
import React from 'react';
import {connect} from 'react-redux';
import {yourAction} from '../your/action/path';
class YourClass extends React.Component {
state = {};
constructor(props){
super(props);
}
componentDidMount(){
this.props.yourAction()
}
render() {
const {data} = this.props; //your data state from redux is supplied as props.
return (
<div>
{!data ? '' : data.map(item => (
<div>{item}</div>
))}
</div>
)
}
}
function mapStateToProps(state) {
return{
data:state.data //state.data if that is how it is referred to in the redux. Make sure you apply the correct path of state within redux
}
}
export default connect(mapStateToProps, {yourAction})(YourClass)
If you do this, <div>{item}</div> will change as you change the data state. The idea is to just map the redux state to your class props - you don't have to map the props back to the state. The render() automatically listens to changes in props supplied by redux. However, if you do want to somehow know redux state change in events, you can add the following functions.
componentWillReceiveProps(newProps){
console.log(newProps)
}
getDerivedStateFromProps(nextProps, prevState){
console.log(nextProps);
console.log(prevState);
}
Can I use an instance of a reactJS component to render a component.
Eg, Let's say my reactJS component is
class myComponent extends Component{
constructor(props){
super(props)
this.state = {
next:false
}
this.alertSomething = this.alertSomething.bind(this);
this.showNext = this.showNext.bind(this);
}
showNext(){
console.log('wow');
console.log(this.state, this, this.state.next);
this.setState({next:true});
}
alertSomething(){
alert('Alert Something')
console.log(this.state, this, this.state.next);
this.setState({next:true});
}
render(){
return(
<div className='column'>
</div>
)
}
}
export default myComponent
Now, inside my another component can I do;
let x = new displayContent.renderComponent();
render(
<x />
//or
<x.render />
)
// I tried both it didn't work, I thought there mush be some other way to achieve this, after all every component is just a javascript object.
Also at the same time, can I call function to make change in its state. Like.
x.someFunction();
where someFunctino is inside that react component, doing setState.
Is it possible? OR am I missing something?
Edit: I clearly understand that when you want to render a react component, you can always do, <component />.
This question is just out of curiosity, can this be done? if not, then why?, I mean how is that different from other javascript objects.
Well, you can use the React.createElement method to render a component:
React.createElement(Component, params)
but with JSX, this is the same:
<Component />
Refer to Multiple components in the React documentation.
This is not how you're supposed to use React. You don't have to handle object instantiations ; React do this for you. Use composition instead.
render() {
return (
<myComponent />
)
}
Also, if you want to set the state of a child component from a parent component, you should probably move the logic in the parent.
Probably you are looking for something like this.
import React, { Component } from "react";
import CamCapture from './CamCapture.js';
export default class ProctorVideoFeed extends Component{
constructor(props) {
super(props);
this.Camera = React.createElement(CamCapture);
}
//this.handleVideoClick = this.handleVideoClick.bind(this);
render(){
return(
<div>
<span>{this.Camera}</span>
<button onClick = {this.Camera.StopRecording}>Stop</button>
</div>
)
}
}
Here StopRecording is a function defined inside CamCapture class.
I have created and rendered another component. On a button click, I want to do some calculations and then change some props on that other component so it will update its view. How would I do this?
If they need to be state values instead of props, that's ok. Can the setState() be called from another component?
class MainComponent extends React.Component {
other: null,
constructor(props, children)
{
//Create the component
this.other = ReactDOM.render( otherReactElement, document.body );
}
...
//An on Click handler
handle: function(evt)
{
//This is what I want to do
other.setProps( { aPropToChange: "new value" } );
}
};
The "setProps" is deprecated. What else can I do to enable something like that?
If you want to pass new props to other, you have to call ReactDOM.render() again with the new props as you can see here.
I have created a jsfiddle where you can see how to update the props and the state correctly.
class MainComponent extends React.Component {
constructor(props)
{
super(props);
this.other = ReactDOM.render( <Hello name="World"/>, document.getElementById('otherComponent') );
}
changeState(evt)
{
this.other.setState({lastName: "setState works"})
}
changeProps(evt){
this.other = ReactDOM.render( <Hello name="New Name" /> , document.getElementById('otherComponent') );
}
render(){
return <div>
<button onClick={this.changeState.bind(this)}>Change state</button>
<button onClick={this.changeProps.bind(this)}>Change props</button>
</div>
}
};
In React, a parent component can change the state of its child component using refs. Using refs, you get a reference to the child component and you can use that reference to invoke a function inside a child component and that function can have the setState() call inside it.
You can read more about react refs here: https://facebook.github.io/react/docs/more-about-refs.html#the-ref-callback-attribute