I am getting undefined while trying to pass array to a class - javascript

I am new to ReactJS and i am having issues with passing an array from one class to another class
Here is my Syntax:
class Application extends React.Component{
constructor(){
super()
this.state = {
data: []
}
}
method_one(){
var array = ["one","two"]
this.state =array
}
render() {
return(
<div>{this.method_one()}
{console.log(this.state.data)}
<AppTwo content={this.state.data}/>
</div>
)
}
}
class AppTwo extends React.Component{
render(){
return<div> {console.log(this.props.content)}</div>
}
}
ReactDOM.render(<Application />,document.getElementById("main"))
The console.log() returns undefined.
Can you help me figure out what I am missing?

Your mistake is that yo try to mutate state of component and the loop happens because you call method constantly.
Try this code:
class Application extends React.Component{
constructor(){
super()
this.state = {
data: []
}
this.method_one = this.method_one.bind(this); //get class context to this method
}
method_one(){
var array = ["one","two"]
this.setState({ data: array });
}
render() {
return(
<div onClick={this.method_one}> //do not call this metod constantly you just need to indicate it
{console.log(this.state.data)}
<AppTwo content={this.state.data}/>
</div>
)
}
}
class AppTwo extends React.Component{
render(){
return<div> {console.log(this.props.content)}</div>
}
}
ReactDOM.render(<Application />,document.getElementById("main"))
Sorry for my English:) Hope its help you.

Related

React, this.props is not defined

I know this is a very common problem and I looked into many other complaints before posting this.
I have class Parent
class Parent extends React.Component {
constructor() {
super();
this.state = {
...
};
}
....
render() {
return (
<MuiThemeProvider theme={materialTheme}>
<Child
ref={...}
groupId={this.state.groupId}
groupUniqueId={this.state.groupUniqueId} />
</MuiThemeProvider>
);
}
}
And a class Child
class Child extends React.Component {
constructor() {
super(props);
this.state = {
...
};
...
}
getUsers() {
const url = `/someurl/${this.props.groupId}`;
...
}
render() {
return (...);
}
}
export default Child;
However, in the class Child, I get an error
"Uncaught ReferenceError: props is not defined"
Is there something obvious that I am missing? Thanks!
This is happening because your this is not referencing a class. It is referring to your function. You can either use arrow functions or bind this to your function in constructor. Just add below line
constructor() {
super(props);
this.state = {
...
}
this.getUsers = this.getUsers.bind(this)
}

Get default state value by receiving prop data - React

I'm new to react.js.
I'd like to get default value of state following_status by receiving props.user.following_status.
I'm passing user object ( user = { following_status: 'following', id:123 } ) to ReactionButton component. ReactionButton component is looks like this:
class RelationButton extends React.Component {
constructor(props){
super(props);
console.log(props.user.following_status) # undefined!!!
this.state = {
following_status: props.user.following_status
}
...
render() {
if (this.state.following_status == 'following') {
<UnFollowBtn/>
} else {
<FollowBtn/>
}
}
RelationButton was called by UserCardHeader component.
const UserCardHeader = (props) => {
const user = props.user;
return(
<header className="user-card--full__header">
<RelationButton user={user}></RelationButton>
</header>
)
}
I don't understand why console.log(props.user.following_status) returns undefined. I googled many websites like those:
React component initialize state from props
accessing props inside react constructor
those answers suggest
class FirstComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
x: props.initialX
};
}
}
but this didn't work for me.
If I add componentWillReceiveProps to the codes above,
componentWillReceiveProps(props){
console.log(props.user.following_status) #=> "following"
this.setState({following_status: props.user.following_status})
}
everything works well. However I think it's weird solution and sometimes doesn't work. Why can't I receive object props in constructor(props) {} section?
Without the full code, we can't tell what's wrong but it is obvious that following_status comes asynchronously to the component and that's why is not accessible right away in the constructor.
To somehow fix it you can detect if props have changed and reset state accordingly in componentDidUpdate.
class RelationButton extends React.Component {
constructor(props){
super(props);
console.log(props.user.following_status) # undefined!!!
this.state = {
following_status: props.user.following_status
}
}
componentDidUpdate(prevProps) {
if(prevProps.user.following_status !== this.props.user.following_status) {
this.setState({ following_status: this.props.user.following_status })
}
}
render() {
// you forgot about return statements :
if (this.state.following_status == 'following') {
return <UnFollowBtn/>
} else {
return <FollowBtn/>
}
}
}

How to use composition in ReactJs

Well here I want to use one method to another component, And for that I found a way through composition.
And this is what I did for that
file1.js
import ProductList from '../../views/Products/ProductList';
class CloseableTab extends Component {
constructor() {
super();
this.tpItem = () => {
console.log("hello, item clicked");
};
}
render() {
return (
<div>
<ProductList
itemChange={this.tpItem} />
</div>
);
}
}
export default CloseableTab;
Then in productList I want to call the "tpItem" method by calling itemChange in prop.
Though before that I tried to console the 'prop' of product list. So, it shows me null object in the console. And for that I used the code below:
ProductList.js
export default class ProductList extends Component {
constructor() {
super();
};
render() {
console.log(this.props);
return { }
}
}
So, this gives me null object in the console.
I'll appreciate your help, thanks.
Did you make constructor props enabled ?
Just pass props parameter in constructor
constructor(props) {
super(props)
}
The constructor for a React component is called before it is mounted.
When implementing the constructor for a React.Component subclass, you
should call super(props) before any other statement. Otherwise,
this.props will be undefined in the constructor, which can lead to
bugs.
Its not ideal to define functions in the constructor of the component, you can declare them outside of constructor and pass them down, also, in ProductList you are trying to render an object which isn't supported. if you don't want to return anything use return null.
Below code works as expected.
class CloseableTab extends Component {
constructor() {
super();
this.tpItem = () => {
console.log("hello, item clicked");
};
}
render() {
console.log(this.tpItem);
return (
<div>
<ProductList
itemChange={this.tpItem} />
</div>
);
}
}
class ProductList extends Component {
render() {
console.log(this.props);
return null
}
}
However you must write it like
class CloseableTab extends Component {
tpItem = () => {
console.log("hello, item clicked");
};
render() {
console.log(this.tpItem);
return (
<div>
<ProductList
itemChange={this.tpItem} />
</div>
);
}
}
Working sandbox

Access custom component methods through ref doesnt work as expected

Can someone explain to me why in SomeClass constructor getLoggerClass method returns undefined,but inside onClick() method it returns logger class?
class App extends React.Component {
constructor(props){
super(props)
this.getLoggerClass = this.getLoggerClass.bind(this)
}
render(){
return(
<div>
<LoggerClass ref={(c)=>{this.loggerClass = c}}/>
<SomeClass app={this} />
</div>
)
}
getLoggerClass(){
return this.loggerClass
}
}
class SomeClass extends React.Component {
constructor(props){
super(props)
this.loggerClass = this.props.app.getLoggerClass()
console.log(this.loggerClass)
this.onClick = this.onClick.bind(this)
}
render(){
return <button onClick={this.onClick}>click</button>
}
onClick(){
console.log(this.props.app.getLoggerClass().console)
}
}
class LoggerClass extends React.Component {
render(){
return <div></div>
}
console(v){
console.log(v)
}
test(){}
}
ReactDOM.render(<App />,document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
It's because the ref function on the LoggerClass node hasn't been executed by the time the constructor of SomeClass gets run. The constructor gets executed when creating the virtual DOM, whereas the ref gets executed when the component actually gets mounted to the real DOM (more info about mounting here). Here's what I think you're looking for, with the relevant code in SomeClass's componentDidMount:
class App extends React.Component {
constructor(props){
super(props)
this.getLoggerClass = this.getLoggerClass.bind(this)
}
render(){
return(
<div>
<LoggerClass ref={(c)=>{this.loggerClass = c}}/>
<SomeClass app={this} />
</div>
)
}
getLoggerClass(){
return this.loggerClass
}
}
class SomeClass extends React.Component {
constructor(props){
super(props)
this.onClick = this.onClick.bind(this)
}
componentDidMount() {
this.loggerClass = this.props.app.getLoggerClass()
console.log('in mounted', this.loggerClass.console)
}
render(){
return <button onClick={this.onClick}>click</button>
}
onClick(){
console.log(this.props.app.getLoggerClass().console)
}
}
class LoggerClass extends React.Component {
render(){
return <div></div>
}
console(v){
console.log(v)
}
test(){}
}
ReactDOM.render(<App />,document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
Here is the culprit :
constructor(props){
super(props)
this.loggerClass = this.props.app.getLoggerClass()
console.log(this.loggerClass)
this.onClick = this.onClick.bind(this)
}
To understand the problem you must understand the, quote mdn, The constructor method is a special method for creating and initializing an object created within a class.
So basically, this constructor method is used to initialize, and so it is called only one time during the class life. So when your SomeClass first renders, the constructormethod is called and in it you define : this.loggerClass as this.props.app.getLoggerClass() (notice here that you called the function immediately at init time) so what is happening is that :
first constructor() is called
in it you called directly the getLoggerClass() method, this method returns the dom node but at init time it is undefined
Try to not call the getLoggerClass method directly but call it later, you do not need to bind it though, just declare in your SomeClass component a method that just calls the getLoggerClass method like so :
callGetLoggerClassFromProps() {
return this.props.app.getLoggerCLass()
}
this way you give the time to the ref to be assigned.

React - props is empty when calling a callback function from child

I have a button on my main component, when its clicked its open an "Approval pannel", And when the OK is clicked I am calling a callback function to the main component and doing some logic.
I want to pass the callback function(My reasons), The problem is that when the callback function is called, the props and state are undefined.
Why is that happening? Please tell me if any info is missing.
I have added a partial code here:
class MainComponent extends React.Component {
constructor(props){
currentActionConfig = {onOkClick: this.onGenericApprovalOkClicked, ...};
}
onCommandApprovalOkClicked(commandText){
console.log(this.props); <- 'undefined'
}
render(){
return <ActionsApprovalPanel currentActionConfig={this.currentActionConfig}/>
}
}
export default class ActionsApprovalPanel extends React.Component {
render()
{
...
return <ChangeIpApproval onOkClick={this.props.currentActionConfig.onOkClick}/>;
...
}
}
Try these changes
class MainComponent extends React.Component {
constructor(props){
super(props); //1. Call super
this.currentActionConfig = {onOkClick: this.onGenericApprovalOkClicked.bind(this), ...}; // 2.bind this
}
onCommandApprovalOkClicked(commandText){
console.log(this.props); <- 'undefined'
}
render(){
return <ActionsApprovalPanel currentActionConfig={this.currentActionConfig}/>
}
}
export default class ActionsApprovalPanel extends React.Component {
render()
{
...
return <ChangeIpApproval onOkClick={this.props.currentActionConfig.onOkClick}/>;
...
}
}
I think you need to make few changes to your React component.
First: In the constructor call super().
Second:: Define currentActionConfig as a state and try using it as this.state.currentActionConfig
Third: Specify the binding on onCommandApprovalOkClicked(). as
onCommandApprovalOkClicked = (commandText) => {} and similary for other functions.
class MainComponent extends React.Component {
constructor(props){
super(props);
this.state = {
currentActionConfig = {onOkClick: this.onGenericApprovalOkClicked, ...}
};
}
onCommandApprovalOkClicked(commandText){
console.log(this.props); <- 'undefined'
}
render(){
return <ActionsApprovalPanel currentActionConfig={this.state.currentActionConfig}/>
}
}
export default class ActionsApprovalPanel extends React.Component {
render()
{
...
return <ChangeIpApproval onOkClick={this.props.currentActionConfig.onOkClick}/>;
...
}
}
Make these changes and see if they work.

Categories

Resources