Access an object from componentDidMount() - javascript

I called the following library in componentDidMount() and it returns an object successfully.
componentDidMount() {
var objData =call.MyLibStart('12121', this);
}
Now I need to use objData in render() section. I also need to access some attribute of the objData such as, objData.
render() {
//I need the object.postate here
}
How can I access an object there? Is using a the state a good idea here?

You can access the object just like #3Dos's answer. If you want to modify the value of objData, then use it as a state. If you only want to render that object or get the value to check for something then a class property is enough.
Make sure you're getting the object the right way:
componentWillMount () {
this.objData = Object.assign({}, call.MyLibStart('12121', this))
console.log('objData: ', this.objData) // inspect the object in debugger to check it's keys
}
The reason with componentDidMount is it only run after the render function. Your app's flow goes like this:
in constructor(): this.objData = null
in render(): this.objData = null
in componentDidMount(): this.objData = some object
At this time render function will not be updated because it will only update if you have made some changes to your state. Since this.objData is not a state so it will always be null in render. So by changing componentDidMount to componentWillMount your objData won't be null when render got called.

What you want is probably to set an instance variable in a constructor so you can access it in your other class methods like for exemple :
class MyComponent extends Component {
constructor (props) {
super(props)
this.objData = call.MyLibStart('12121', this)
}
render () {
// Do whatever you like with this.objData
return null
}
}

Unless you need access to mounted components, you could set it as initial state in the constructor:
constructor(props) {
super(props)
this.state = {
objData: call.MyLibStart('12121', this)
}
}
render() {
// use this.state.objData here
}

Related

componentWillMount check on undefined before api request will resolve

I have a component that triggers some methods that depend on async API request. I use componentWillmount to check some props. If this prop is true I trigger some function otherwise false. But the problem is, that first time the prop is undefined, only after some time it will become false or true. How to check it and wait until request resolved?
componentWillMount = () => {
this.props.init(parseInt(this.props.tagId, 16), this.props.accessToken);
if (!this.props.notFound && !this.props.person) this.props.onFreeTag();
};
Use componentWillReceiveProps lifecycle function, something like:
componentWillReceiveProps = (nextProps) => {
if (!nextProps.notFound && !nextProps.person)
nextProps.onFreeTag()
}
}
It appears that first time when the component loads or get called your are passing it some value which is undefined initially and later becomes available. For example lets say you have a parent component as following
class Parent extends React.Component {
constructor() {
this.state = {0}
}
render() {
<Child value={this.state.value} />
}
}
As you can see, initially the state doesn't have a property value so the Child will receive undefined for this.props.value. It will only receive not undefined when some parent function changes it like this,
class Parent extends React.Component {
constructor() {
this.state = {0}
}
onAction() {
this.setState({value: true})
}
render() {
<Child value={this.state.value} />
}
}
So if on some event parent calls its OnAction it will change the state and Child will get this.props.value as true but as Child will be already rendered componentWillMount hook will not get triggered but componentWillReceiveProps will. So if you want to use the prop in componentWillMount make sure its passed at the first render of the child and if that is not possible use componentWillReceiveProps to process the props

React. Cannot start function inside the getDerivedStateFromProps

I cannot understand, why when I try to start the function getTodosList inside the getDerivedStateFromProps the method - it always retrun to me the TypeError - Cannot read property 'getTodosList' of null.
Also after I start use the getDerivedStateFromProps - my function does not start in componentDidMount too...
What is I'm doing wrong? (
import React, { Component } from 'react';
import {Doughnut} from 'react-chartjs-2';
class Chart extends Component {
constructor(props) {
super(props);
this.state = {
// some state...
}
getTodosList = (todos) => {
console.log(todos);
const all = [];
const done = [];
// some logic...
}
componentDidMount() {
const { todos } = this.props.state.iteams;
console.log('componentDidMount', todos);
this.getTodosList(todos);
}
static getDerivedStateFromProps(nextProps, prevState) {
const { todos } = nextProps.state.iteams;
console.log(this.getTodosList, prevState.datasets, 'componentWillReceiveProps', todos);
this.getTodosList(todos); // TypeError: Cannot read property 'getTodosList' of null
}
getDerivedStateFromProps is a static property of the class (as indicated by the static keyword in front of it). This means it doesn't have access to any instance functions/properties.
Declare your getTodosList as static as well (if it also doesn't use any instance properties) then call Chart.getTodosList(todos).
Edit:
If you call setState in getTodosList, you can change it to return the state object instead, then you can construct/update your state based on the returned object from your calling function.
Eg.
static getTodosList = todos => {
...
return { someState: someData }; //instead of this.setState({ someState });
}
static getDerivedStateFromProps() {
...
return Chart.getTodosList(todos);
}
You also don't need the componentDidMount if it's doing the same thing as getDerivedStateFromProps.
getDerivedStateFromProps is a static method, it will not have the access of any instance property/method, means this will not be available inside that method.
Use componentDidUpdate to perform the operation you want on state/props change.
You need to put the check between prevState/prevProps vs the new values.
componentDidUpdate(prevProps, prevState, snapshot) {
// compare this.state and prevState or compare the props values
// and perform the operation
}

Reactjs: Uncaught Error: Maximum update depth exceeded when trying to update state

I am trying to do a simple thing:
check if a parameter is on the URL and then set a state for my component. This state will determine if some html code should be displayed or not.
Basically this dummy sample may give you an idea of what I have:
class Lalala extends Component {
constructor(props) {
super(props);
this.state = {showStatement : false}
}
parseURLParams(urlParams) {
if (urlParams.indexOf('blabla')> -1) {
this.setState({
showStatement: true
})
}
}
render() {
const { location } = this.prop
this.parseURLParams(location.search);
}
}
So, as you can see, every time it renders, it calls the parseURLParams function which tries to set the state, and, of course, when the setState is called, the render function is being called again, causing a infinite loop which ends up returning this error in the console.
Could you guys tell me a better way to set this state? once this is something that doesn't depend on an event, I am a bit confused.
Thanks
cause you using setState in render. It willbe render -> setState -> render-> setState -> render... You should move this.parseURLParams(location.search); to other lifecycle like this
componentWillReceiveProps(nextProps) {
if(JSON.stringify(nextProps.location) !== JSON.stringify(this.props.location)){
this.parseURLParams(this.props.location.search);
}
}
Try setting state in a different lifecycle hook, like componentDidUpdate. Also, if the prop value you want is available at the initial render, you'll want to set it in state there as well:
class Lalala extends Component {
constructor(props) {
super(props);
this.state = {
showStatement : false,
showBrokerStatements: props.location && props.location.search && props.location.search.indexOf('blabla')> -1
}
}
componentDidUpdate() {
this.parseURLParams(this.props.location.search);
}
parseURLParams(urlParams) {
if (urlParams.indexOf('blabla')> -1) {
this.setState({
showBrokerStatements: true
})
}
}
render() {
const { location } = this.prop
}
}

Where to set props-dependant state in a React component?

Let's say that I want to set the initial state of a component depending on a variable from the parent that is passed via props.
class MyClass extends Component {
constructor(props) {
super(props);
this.state = {};
}
I want to set the state like this:
if (this.props.foo === 'bar') {
this.setState({foo: 'bar'});
} else {
this.setState({foo: 'notBar'});
}
I put it in ComponentDidMount() and it seems to work. However, should I move it to the constructor and use the syntax this.state = {...}? Or does it belong to ComponentWillMount()? If so, is there a guarantee that the state will be rendered in time? (foo is displayed as a text field)
Since your state is assigned based on the value of proper, a good place to handle it is to assign it in the two places
ComponentWillMount/Constructor/ComponentDidMount: These are executed only once, when the component is mounted. One more thing is that if you setState in componentWillMount or componentDidMount, the it should be atleast initialised in contructor so that you don't get an undefined state error.
ComponentWillReceiveProps: This lifeCyle function is not called at the time of mounting but everytime after that the parent rerenders, so any time the prop foo changes from parent , it can be assigned to state again here
Do it like
constructor(props) {
super(props);
this.state = {
foo: ''
}
}
componentWillMount(){
if (this.props.foo === 'bar') {
this.setState({foo: 'bar'});
} else {
this.setState({foo: 'notBar'});
}
}
componentWillReceiveProps(nextProps){
if (nextProps.foo === 'bar') {
this.setState({foo: 'bar'});
} else {
this.setState({foo: 'notBar'});
}
}
Yes, it is valid to initialize state in the constructor: React Constructor Docs
So your code would be as follows:
class MyClass extends Component {
constructor(props) {
super(props);
if (props.foo === 'bar') {
this.state = {foo: 'bar'};
} else {
this.state = {foo: 'notBar'};
}
}
}
However, be aware that any change to the props in the parent will not be updated in this component, since it's only set on the constructor.
So this is only a good way to initialize state if you do not expect the parent props to change (but that is probably rare). Have a look at Lifting State Up for a guide to architect your components in a better way.

ReactJS: Accessing Child Final State

This may seem as a bit of a redundant question but I'm trying to access the final state of a child in React, after it has updated. I've been looking into the React LifeCycle docs (I think that might be the issue, but not sure), searched high and low, and can't quite figure it out.
I've got a component which needs to access the (final) value of the state of a child, once that child has done some updating (AJAX request which then does a few this.setStates).
So far, I'm able to access the entire state of that child, accessing through a ref (Inside componentDidMount), but when I try to access a specific value of said state, it returns null or undefined.
Here's some example code to explain (I'll try to spare you as much useless code as possible):
class Layout extends Component {
constructor(props) {
super(props);
}
componentDidMount(){
// This gives me the updated State where pageTitle = "Whatever"
console.log(this.refs.child1);
// However this gives me the initial State where pageTitle = null
console.log(this.refs.child1.state.pageTitle);
}
render(){
return (<div>
{React.cloneElement(
this.props.children,
{ref: 'child1'}
)}
</div>);
}
}
And here's the child component for reference (note: i'm using axios for my ajax requests):
export class ChildComponent extends Component {
constructor(props) {
super(props);
this.state = {
resultData: result,
pageTitle: null
}
}
componentDidMount(){
this.serverRequest = axios.get(apiUrl)
.then(function(result){
this.setState({
resultData: result,
pageTitle: result.pageTitle
});
}.bind(this))
}
render(){
return(<div>
{use of different this.state.resultData values works fine here}
</div>)
}
}
Appreciate any help that comes this way
To use a callback, add this code to the parent element:
handleAsyncDone(data) {
// Do whatever it is people do with data
}
And then pass that function to the child component, and in the childcomponent, add
this.props.handleAsyncDone(this.state);
Which will pass the child state back up to the parent.

Categories

Resources