I am trying to pass the onClickItem function down to the Card component as a prop, so that when it is clicked the state in the current component is updated.
class CurrentComponent extends Component {
...
constructor(props) {
super(props);
this.onClickItem = this.onClickItem.bind(this);
...
onClickItem() {
this.setState({something: true});
}
static cards = [
{ position: 8, element: <Card position={8} onItemClick={this.onClickitem}/> }
];
render() {
...
}
The this inside the static array is undefined. I was wondering how I can pass the function down. It is possible to move the array declaration inside the render, but I do not want it initialized every time the component renders. Any insight appreciated!
take the keyword "static" off the array declaration and it will work fine.
to understand the reason why it works without static and understand how static is treated in general you can look at this code -> transpiled on right
https://www.typescriptlang.org/play/#src=class%20context%20%7B%0D%0A%20%20%20%20somethingelse%20%3D%205%3B%0D%0A%20%20%20%20testing%20%3D%20%5B%0D%0A%20%20%20%20%20%20%20%20this.somethingelse%0D%0A%20%20%20%20%5D%0D%0A%7D%0D%0A%0D%0Aclass%20contex2t%20%7B%0D%0A%20%20%20%20somethingelse%20%3D%205%3B%0D%0A%20%20%20%20static%20testing%20%3D%20%5B%0D%0A%20%20%20%20%20%20%20%20this.somethingelse%0D%0A%20%20%20%20%5D%0D%0A%7D
Related
I am getting stuck while using react, wherein, I am passing a function from a parent component to multiple children components. That function calls other functions that also reside within the parent component.
The children components do successfully start the function, but unfortunately, the function fails because it seems to not have the same context from within the children's elements, eg. it begins calling the other functions stored within the parent element, and receives undefined. This is strange because the error is coming from the parent component file, not the child component file.
I was not sure whether to pass all the functions to the children elements, which feels rather bulky, and also feels like I would still be missing important function context.
I have tested running the same function on the parent component and it has no issues, almost like the function context from the parent component is not passed to the child component, only the function itself.
Is that correct?
Here is an example where the child component has a button to click that would run the function that was passed from the parent component and includes running other functions from within the parent component, updating state and making changes, etc.
Parent element:
class Content extends Component {
constructor(props) {
super(props);
this.state = {
name: "React",
toggle: true,
...
};
}
toggleComponent(name) {
this.toggling(name); // THIS IS WHERE THE ERROR OCCURS ON THE CHILD ELEMENT, undefined.
}
toggling(name) {
does some stuff...
}
render() {
return (
<Comp toggleComponent={this.toggleComponent}/>
)
}
Child element:
class Demo1 extends Component {
constructor(props) {
super(props);
this.state = {
name: "React"
};
}
render() {
return (
<div className="button" onClick={() => this.props.toggleComponent('theCompName')}>Continue</div>
)
Let me know what can be done to pass the additional context to the children components or if there is a better way to do this.
Thanks, you are all very smart.
In your constructor for your Content class, try binding your toggleComponent function to the class using .bind():
constructor(props) {
super(props);
this.state = {
name: "React",
toggle: true,
...
};
this.toggleComponent = this.toggleComponent.bind(this);
}
Class methods are not "bound" to the class by default. This means that your this keyword in toggleComponent does not refer to the Content class until you specify it using .bind().
Hope this helps!
More info can be found here: https://reactjs.org/docs/handling-events.html
Use arrow syntax in the parent component's functions. That will allow the functions in the parent component to execute in the parent component's context. Otherwise you'll have to do a bunch of binding(this) crap to make that work properly.
I have a react component that has to pass a method to its children so that they can modify the state. So I created a function that allows to do that. I know I should bind the parent component to the this parameter of the function so that the children can successfully modify the state. The reason I want to do this is silly: I just don't know what to name the bound version ¯\_(ツ)_/¯. So what wanted to do is:
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.modifyState = this.modifyState.bind(this);
}
modifyState() { /* blah blah*/ }
render() {
return(
<Child modifyState={this.modifyState} />
);
}
}
Now my question is:
Is there a reason why I really don't want to do this, can it cause any problems?
The reason I ask is, if there were no downsides, why not have this be the default behavior of it, in other languages this is always an instance of the class where the function (method) is defined. If you wanted the current behavior (this is the object who called the function from my understanding) just declare a global function.
I have a number of methods in a React class component. The component itself receives a number of props.
I am wondering if I should take the props and add each of them as this.propName in the constructor and then access the props using this.propName. Here is an example. What is best practice?
const classComponent = class classComponent extends Component {
constructor(props) {
super(props)
this.propA = props.propA
this.propB = props.propB
}
methodA() {
console.log(this.propA)
}
}
Alternative
const classComponent = class classComponent extends Component {
constructor(props) {
super(props)
}
methodA() {
console.log(this.props.propA)
}
}
Official documentation of React.js in State and Lifecycle section says:
While this.props is set up by React itself and this.state has a special meaning, you are free to add additional fields to the class manually if you need to store something that is not used for the visual output.
In your case, most likely it should stay as a prop. Whenever you pass anything as a parameter, which in React.js philosophy would be a prop, it's most likely an ingredient of the visual effect.
Once you create a variable it uses memory and, even if you are referencing a type, like an array or an object, you make your file bigger. Creating new names for variables already accessible to your class/function make no sense, so don't do it.
The way you handled the props does not allow the component to update when it receives new props; mainly because constructor is only called once--at the creation of the component.
A better way to do it is to use Destructuring assignment in the render function:
render() {
{propA, propB, ...rest} = this.props;
//Rest code here, using propA, propB
//However, don't use this.propA, or this.propB
}
If you still like to do the way you want to do, you have to add the following function inside your component, to make your component update whenever it receives new props:
componentWillReceiveProps(nextProps) {
this.propA = nextProps.propA;
this.propB = nextProps.propB;
}
As you can see, unnecessary code had to be included, so I think this is a wrong way to do it!
Note: I encounter this specific problem using React Native, but I guess this goes for React in general as well.
I have a react component built using React.Component.
I don't need to set state, but I do have props. My proposed syntax was as follows:
class Header extends Component {
constructor(props) {
super(props);
}
render() {
return <div>{this.props.title}</div>;
}
}
I understand I can use a function to construct this component, like this:
const Header = (props) => {
return <div>{props.title}</div>;
}
But I prefer the former, because my component will grow, might have state etc, and I just want to keep all my components built in a similar fashion.
Now, my linter complains about having a useless constructor, but how else do I access the props while keeping a class constructor instead of a function constructor?
If you want to use this.props in the constructor, you need to pass props to super. Otherwise, it doesn't matter because React sets .props on the instance from the outside immediately after calling the constructor.
So just simply remove constructor() if useless
you can access props without constructor in a class using "this", like this:
class XXXXXX extends React.Component {
render() {
return (
<div>{this.props.value}</div>
)
}
}
So i love this React thingy, and we have this so called 'stateless' functions to help us build a 'dumb' component. Now i want to create a class that produce a stateless function. Why you may ask, well i love the idea of inheritance and wanting to 'extend' my stateless function basic capability, said i want to add a helper function as a statics that binds to the function itself.
I ended up with this code
class Stateless {
constructor() {
return this.render.bind(this)
}
nanny() {
// do something
}
render(props) {
// yeay! a stateless function!
// plus i can access nanny by using this.nanny()
}
}
And when i extend it, i can see that the inheritance is working well.
BUT, if then i initialize the class:
const stateless = new Stateless()
Why can't i access stateless.nanny even tho inside the render function i can see that this.nanny is accessible? Where does the nanny lives? Does it binded to the render function?
EG:
class Stateless {
constructor() {
return this.render.bind(this)
}
nanny() {
console.log('foo')
return true
}
render(props) {
console.log(this.nanny()) // -> returns 'foo'
return 'JSX'
// this should return a JSX
}
}
const stateless = new Stateless() // -> stateless IS a function
stateless()
// 'foo'
// true
// JSX
stateless.nanny
// undefined
While clearly inside render when i called this, there is nanny there. But when i
refer it outside, the nanny is gone. I thought nanny should be a static property of the stateless, right?
If you are returning object from constructor - new will return that object instead of the instance of the class being constructed (more info).
Therefore line
const stateless = new Stateless()
will assign to stateless variable result of this.render.bind(this) - that is reference to method (function) of Stateless class, that is not an instance of Stateless. Therefore stateless.nanny makes no sense - as function render does not have such property defined. On the other hand calling bound render function directly - produce the expected result.
All in all - i strongly do not recommend you to return anything from constructor (unless you are dealing with some really weird requirements like controlling number of instances and such). It makes code hard to understand and maintain.
Your example should work if you remove this.render.bind(this) from your constructor.
It should also work, if you just remove return from the constructor:
constructor() {
this.render.bind(this)
}
However, you might actually be looking to create a higher order component that can enhance the component that it wraps.
Your higher order component is a function that returns a class that renders the component that it passed to it:
import React from 'react'
function HigherOrderComponent(WrappedComponent) {
return class Enhancer extends React.Component {
constructor(props) {
super(props)
}
exampleFunc() {
// Code here
}
render() {
return <WrappedComponent exampleprop={ this.exampleFunc } />
}
}
}
export default HigherOrderComponent
Then you can import HigherOrderComponent into your stateless dumb component file and wrap the export:
import React from 'react'
import HigherOrderComponent from './HigherOrderComponent'
const DumbComponent = (props) => {
// Return JSX
// You can use props.exampleprop
}
export default HigherOrderComponent(DumbComponent)
Here are some articles that you can read on higher order components:
https://facebook.github.io/react/docs/higher-order-components.html
https://medium.com/#franleplant/react-higher-order-components-in-depth-cf9032ee6c3e