How to set variable from parent inside child's componentDidMount react? - javascript

I am trying fetch the information from Api request in child component. The problem is that I have faced accessing parent's props. More precisely how to get parent's props and set it inside componentDidMount()?
Parent component
class Parent extends Component {
constructor(){
super()
}
...
<Child id={id}/>
...
export default Parent;
Child component
class Child extends Component {
constructor(){
super()
this.state = {
id:'',
}
}
// I need somehow set parent's "id" inside the url
componentDidMount() {
const url = `https://api.../${id}?api_key=${apiKey}`;
axios.get( url )
...
};
render(){
const { id } = this.props;
console.log('Child id ' + id) // here I see all ids
return(
<div className="item" key={id}>
<p>{id}</p> // here as well
</div>
)
}
}
Child.propTypes = {
item: PropTypes.object
}
export default Child;
Maybe I am looking for in the wrong place and I need just change logic.
I will be grateful for any advice

To access props from anywhere in your Child component you need to pass props to your constructor, then you just access it using this.props.
This should work:
class Child extends Component {
constructor(props){
super(props)
this.state = {},
}
componentDidMount() {
const id = this.props.id
const url = "https://api.../$" + id + "?api_key=${apiKey}";
axios.get( url )
...
};
}

If you have a constructor in a component the props should always be passed to the constructor and also to React component using super()
constructor(props){
super(props)
}
In your case if you have to use your parents props you should also pass the parents props to child also and with same syntax in constructor you can use props that you passed in anywhere of the child component and you can set that props in componentDidMount as well

Related

passing state value to a child component via props

i'm trying to pass the value entered by the user from the app component to the passTicket component. I tried invoking props to pass this state data but I keep getting an undefined error when attempting to access it. I'm new to react and it would be great if someone can help me make sense of what i'm getting wrong. This is a sample of what i'm trying to achieve.
This is my main component:
class App extends Component {
constructor(props){
super(props);
this.state = {
ticket:"",
};
this.changeTicket = this.changeTicket.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.keyPress = this.keyPress.bind(this);
}
changeTicket(e){
this.setState({
ticket : e.target.value,
})
}
handleSubmit(){
this.setState({
updatedTicket: this.state.ticket
});
}
keyPress(e){
if (e.keyCode ===13){
this.handleSubmit();
}
}
render() {
return (
<div className="App">
<header className="App-header">
<input type="text" placeholder="ENTER TICKET NUMBER" value={this.state.ticket} onKeyDown={this.keyPress} onChange={this.changeTicket}/>
</header>
</div>
);
}
}
and i'd like to be able to store the updatedTicket value in a variable which I can use in my PassTicket component. this is what i've attempted so far but the error it occurs is the following Uncaught TypeError: Cannot read property 'updatedTicket' of undefined
this is what my second component looks like:
class PassTicket extends Component {
transferredTicket(){
const myTicket = this.props.state.updatedTicket;
return myTicket
}
render() {
return (
<p>{this.transferredTicket()}</p>
);
}
}
When passing down a property from a parent to a child component, the property will be stored onto the props by the name it's passed through. For example:
class Parent extends Component {
state = {
ticket: '',
}
render() {
return <ChildComponent updatedTicket={this.state.ticket} />
}
}
class ChildComponent extends Component {
static propTypes = {
updatedTicket: PropTypes.string,
}
static defaultProps = {
updatedTicket: '',
}
render() {
return (
<div>{this.props.updatedTicket}</div>
);
}
}
In the example you've given, it doesn't seem like you're passing the state down to the component you're trying to access it in. In addition, it seems like you're trying to access the updatedTicket as a property of a state object, so just beware of how you're accessing your props.
Therefore, in order to access the updatedTicket property on the child component, you'll first need to import the PassTicket component, instantiate it in the parent (App) component, and pass the property down:
<PassTicket updateTicket={this.state.ticket} />
You would then be able to access the string in the PassTicket component like so - this.props.updateTicket
So .state in react is a local state that is only visible to the individual component. You can read more about it here: https://reactjs.org/docs/state-and-lifecycle.html
In order to pass your state around, you need to use the props system. So where you instantiate your component, you can pass in the state of the parent. For example:
<PassTicket ticket={this.state.updatedTicket}/>
Then inside your PassTicket render function, you can access the ticket prop:
render() {
const { ticket } = this.props
return (
<div>{ticket}</div>
)
}

Reactjs : How to change props data from parent component that already distribute to child component?

I just creating a project and use a several component for a page and pass data by using props to each components. The problem is, when I have already change data from parent component to child component by using props and I have update the data from parent component, the child component still using the old data.
The example is just like this:
class Child extends Component{
constructor(props){
super(props);
this.state = {
variabel : props.variable
}
}
render() {
return (
<div>
<h1>{this.state.variable}</h1>
</div>
)
}
}
class Parent extends Component{
constructor(props){
super(props);
this.state = {
variabel : 'Hello'
}
}
render() {
return (
<div>
<Child variable={this.state.variable} />
</div>
)
}
}
So, when I run the page and update the variabel state in Parent Component, Child Component still show the old value. How to make it updated as the Parent Component data? Or I must using Redux for this case?
In general you'll only want to keep one particular piece of state in one place. If you reassign it in the constructor of Child, it will not update when the parent's state updates. So something like this pattern should work:
class Child extends Component{
// Note that no constructor is needed as you are not initializing any state or binding any methods.
render() {
return (
<div>
<h1>{this.props.variable}</h1>
</div>
)
}
}
class Parent extends Component{
constructor(props){
super(props);
this.state = {
variable : 'Hello'
}
}
render() {
return (
<div>
<Child variable={this.state.variable} />
</div>
)
}
}
A warning note about not initializing state with props is in the React docs for constructor, as a matter of fact.
Mitch Lillie's answer is the correct one. You should have only one source of truth.
In general, it's a good idea to keep the state in the nearest common ancestor of the components that depend on the state. Then you pass the props down.
If, however, you need to keep a copy of the prop in the child state, you should use the life cycles that React provides.
Codepen Live Demo
class Child extends React.Component {
constructor(props) {
super(props);
this.state = {
variable: props.variable,
};
}
componentDidUpdate(prevProps, prevState, snapshot) {
if (this.props.variable !== prevState.variable) {
this.setState({
variable: this.props.variable,
});
}
}
render() {
const varState = this.state.variable;
const varProps = this.props.variable;
return (
<div>
Child props: {varProps}
<br />
Child state: {varState}
</div>
);
}
}
class Parent extends React.Component {
constructor(props) {
super(props);
setInterval(this.updateTime, 1000); // refresh every second
this.state = {
variable: new Date().toLocaleString(),
};
}
updateTime = () => {
this.setState({
variable: new Date().toLocaleString(),
});
}
render() {
const time = this.state.variable;
return (
<div>
<div>
Parent: {time}
</div>
<Child variable={time} />
</div>
);
}
}
ReactDOM.render(
<Parent />,
document.getElementById('container')
);

Redux: passing information to/from window child

Essentially I am trying to create an app where it has a note-pad feature that opens up a window child and passes some information from the parent (which holds the redux state) to it.
However, I am having trouble on how to send the information from the child to the parent, specifically dealing with dispatching action.
I was able to figure it out on passing from parent to child as so without using Redux:
Parent Window
class NavBar extends React.Component {
constructor() {
super()
this.handleNotesMenu = this.handleNotesMenu.bind(this)
}
handleNotesMenu() {
window.id = this.props.id
window.userName = this.props.userName
window.currentReduxState = store.getState()
const notePad = window.open('NotePad', 'notes', 'toolbar=0,status=0,width=715,height=325')
}
Child Window
export class NotePad extends React.Component {
constructor(props) {
super(props)
this.handleChange = this.handleChange.bind(this)
this.state = {
notes: window.opener.state.getIn(['plan', 'notes'])
}
}
handleChange(tabID) {
return e => {
const state = {}
state[tabID] = e.target.value
this.setState(state)
}
}
render() {
return (
<textarea
id="saveArea"
value={this.state.notes}
onChange={this.handleChange('notes')}
name="textarea"
/>
)
}
}
I thought out about that adding action dispatcher to the child was hard, so I was thinking somehow incorporate with sessionStorage. But then I got stumped on how the parent window is able to listen to listenStorage on the fly.
Any thoughts? What would be the best practice when it comes to dealing with window child in React/Redux?
Send a method as prop which will take the returning data as argument from child component and call this method in your childcomponent with that data...like this....
In parent component.....
someMethod(data){
// do something here with data
}
In your render method pass this method to child component as...
<ChildComponent someMethod={this.someMethod} />
Now in your child component call that method like this...
this.props.someMethod(someData);
And that's it your are done...
You have passed the data your parent component without dispatch ... In that someMethod() you can do whatever you wanna do with that data

How to pass an Array and access it within React Lifecycle

I'm using Mongo/Meteor 1.3/React. In my simple example I use an wrapper React component to query the Mongo collection and create an Array. When passing to the Child component, it seems like the Array object is not ready when constructor is called - meaning I can't access the props.
This feels like it must be a common problem. Should I be using a different React Lifecycle Component? Or adding some form of waitOn function? Any advice appreciated!!
Parent Component
export default class BulkMapWrapper extends TrackerReact(React.Component) {
constructor() {
super();
const subscription = Meteor.subscribe("listing",{sort: {_id:-1}})
this.state = {
eventsData: subscription
}
}
render () {
var markerArray = []
markerArray = ...
return(
<div className="panel panel-default">
<div className="panel-body">
<FourthMap
mapParams = {manyEvents}
markers = {markerArray}
/>
</div>
</div>
)
Child Component
export default class GooleMapComponent extends Component {
constructor(props){
super(props)
console.log(this.props.markers);
You should use the componentDidMount function to get the data and then set a new state with the resulting data.
class GetData extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
componentDidMount() {
const subscription = Meteor.subscribe("listing",{sort: {_id:-1}});
this.setState({
eventsData: subscription
});
}
}
You can then pass down the state from the GetData component as props to its children or explicitly to another component in the render function.
This is generally how you should handle AJAX requests in React but I'm not sure if this will translate well to use in Meteor.

Reactjs, parent component, state and props

I m actually learning reactjs and I m actually developping a little TODO list, wrapped inside of a "parent component" called TODO.
Inside of this parent, I want to get the current state of the TODO from the concerned store, and then pass this state to child component as property.
The problem is that I dont know where to initialize my parent state values.
In fact, I m using ES6 syntax, and so, I dont have getInitialState() function. It's written in the documentation that I should use component constructor to initialize these state values.
The fact is that if I want to initialize the state inside of my constructor, the this.context (Fluxible Context) is undefined actually.
I decided to move the initialization inside of componentDidMount, but it seems to be an anti pattern, and I need another solution. Can you help me ?
Here's my actual code :
import React from 'react';
import TodoTable from './TodoTable';
import ListStore from '../stores/ListStore';
class Todo extends React.Component {
constructor(props){
super(props);
this.state = {listItem:[]};
this._onStoreChange = this._onStoreChange.bind(this);
}
static contextTypes = {
executeAction: React.PropTypes.func.isRequired,
getStore: React.PropTypes.func.isRequired
};
componentDidMount() {
this.setState(this.getStoreState()); // this is what I need to move inside of the constructor
this.context.getStore(ListStore).addChangeListener(this._onStoreChange);
}
componentWillUnmount() {
this.context.getStore(ListStore).removeChangeListener(this._onStoreChange);
}
_onStoreChange () {
this.setState(this.getStoreState());
}
getStoreState() {
return {
listItem: this.context.getStore(ListStore).getItems() // gives undefined
}
}
add(e){
this.context.executeAction(function (actionContext, payload, done) {
actionContext.dispatch('ADD_ITEM', {name:'toto', key:new Date().getTime()});
});
}
render() {
return (
<div>
<button className='waves-effect waves-light btn' onClick={this.add.bind(this)}>Add</button>
<TodoTable listItems={this.state.listItem}></TodoTable>
</div>
);
}
}
export default Todo;
As a Fluxible user you should benefit from Fluxible addons:
connectToStores.
The following example will listen to changes in FooStore and BarStore and pass foo and bar as props to the Component when it is instantiated.
class Component extends React.Component {
render() {
return (
<ul>
<li>{this.props.foo}</li>
<li>{this.props.bar}</li>
</ul>
);
}
}
Component = connectToStores(Component, [FooStore, BarStore], (context, props) => ({
foo: context.getStore(FooStore).getFoo(),
bar: context.getStore(BarStore).getBar()
}));
export default Component;
Look into fluxible example for more details. Code exсerpt:
var connectToStores = require('fluxible-addons-react/connectToStores');
var TodoStore = require('../stores/TodoStore');
...
TodoApp = connectToStores(TodoApp, [TodoStore], function (context, props) {
return {
items: context.getStore(TodoStore).getAll()
};
});
As a result you wouldn't need to call setState, all store data will be in component's props.

Categories

Resources