Call a static function into the class React ES6 - javascript

I have the following ReactJS class:
import React from 'react'
export class Content extends React.Component {
static getValue(key) {
return key
}
render() {
let value = this.getValue(this.props.valueKey);
return <span dangerouslySetInnerHTML={{__html: value}} />
}
}
But I have the following error:
TypeError: this.getValue is not a function
I don't understand. Is this the good way to call a static function? I think react is doing something with statics, but I don't know what.

A static method needs to be accessed on the class not an instance. So in your case, use:
Content.getValue()
However, a static method won't be able to access this -- I don't think you want the method to be static based on your code sample above.
More: Static Members in ES6

You can access from within the class as this.constructor.getValue.
Edit: I've added a JSFiddle here. The only change I made was adding the function call from the constructor and removing the dangerously set innerHTML - As shown, you can access the getValue static from this.constructor, and works just fine.

Related

Undefined 'this' when handing class method to React component

I have API methods for my React app within an API class:
class API {
constructor() {
//setup axios
}
async deleteEquipment(item) {
return this.axios.delete(...paths and stuff..)
}
}
export default API(config)
This works fine for most of my code, except when I need to hand it to components through the props, like so:
import API from '../path/to/api.js'
.. code
<PageTable
deleteItem={API.deleteEquipment}
...more props
/>
This doesn't work as it seems this used in the class to reference axios is now undefined.
this.axios leads to Cannot read properties of undefined (reading 'axios')
I have tried late binding, to bind the method to the class like so:
<PageTable
...more props
deleteItem={API.deleteEquipment.bind(API)}
/>
but it doesn't seem to have much effect. Any ideas how to keep the this reference to the class when the method is called by PageTable ?
Thanks in advance!
try to bind deleteEquipment in constructor
this.deleteEquipment = this.deleteEquipment(this);
also use await with async functions

Typescript Vuex - How to define a state with a setter and getter?

In the vuex store I want to initialize a state called _token. When I'm trying to access the property within the same class, it gives me the error message that the setter for _token is not defined. Anyone has an idea why only the getter is available?
export default class Api extends VuexModule {
public _token = '';
#Action
public async [VuexActionsApi.VerifyUser](data: any): Promise<IResponseState> {
const vuexInstance = this;
// this is not working
vuexInstance._token = "test";
}
If you are going to use class decorators then you must import them (and install the package) like this:
import Action from 'vue-class-component'
Although I might advise against that syntax as it is being deprecated in vue3, see here:
https://github.com/vuejs/rfcs/pull/17#issuecomment-494242121
It seems to work now, when i defined the state like this:
public data = {
bearerToken: undefined
};
Now the setter and getter functions are created correctly. Someone has an idea why the first approach didn't work?

Why do propTypes live on the class but not other methods?

I read that using static for propTypes puts the it on the class instead of the instance of the React component. I don't get the difference between putting something on the class vs. the instance though. Why is propTypes on the class but not methods like render and componentDidMount, or other custom made methods inside the component?
It's for the same reason as the keyword static. This is un-changing static metadata that helps describe your class. It can be accessed without needing to instantiate your class (accessed without calling the constructor).
class example extends Component {
static propTypes = {
something: PropTypes.object,
}
static displayName = "ExampleDisplay";
render() {
return <div />;
}
}
// I can access static properties here directly
var types = example.propTypes;
var name = example.displayName;
// I can NOT access the render method without instantiating the class.
var instance = new example(); // <- this calls the constructor and creates an instance.
var renderFn = instance.render;
The question is really: why should I need to create the class just to read the propTypes or displayName? you shouldn't need to. that's why you have static.

How should functions be written within a React class?

I'm trying to adapt code from a SO answer, with functions and variables written as below:
const getIntervals = n=> availability=> {
}
let availability = [
]
Are those normally fine to use in a react class (see below) or do they need to be rewritten?
class Calendar extends React.Component {}
The reason for asking is that I use a React implementation for Rails and do get an error including that function and variable naming pattern.
Pure Functions, which dont modify the passed value, are always fine to use anywhere.
Its also fine to use them in a React Class directly, but common functions like string modifications, array sorting algorithms, which you are using a lot across your app and classes should go in a separate module like
// my-helpers.js
export const countKeysInObject = (data) => {
if (typeof data !== "object" || Array.isArray(data)) return 0;
Object.keys(data).length;
}
some other file..
import { countKeysInObject } form 'my-helpers'
// And you can use it everywhere..
If you are using class and extending Component, you can use simple methods for most things:
class Calendar extends React.Component {
constructor(props) {
this.date = props.date;
}
render() {
return <span>{this.date.toString()}</span>;
}
}
Calendar.propTypes = {
date: React.PropTypes.date.isRequired
};
You cannot use methods for propTypes or anything that would be an initial field if you were using an object literal. Those need to be attached after the class has been declared (propTypes) or in the constructor (initial state).

How to access child component functions via refs

The docs for React state that component functions can be accessed by a parent component via refs. See: https://facebook.github.io/react/tips/expose-component-functions.html
I am attempting to use this in my application but run into an "undefined is not a function" error when the child function is called. I'm wondering if this has anything to do with using the ES6 format for React classes because I don't see any other differences between my code and the docs.
I have a Dialog component that looks like the following pseudocode. The Dialog has a "Save" button that calls save(), which needs to call the save() function in the child Content component. The Content component collects information from child form fields and performs the save.
class MyDialog extends React.Component {
save() {
this.refs.content.save(); <-- save() is undefined
}
render() {
return (
<Dialog action={this.save.bind(this)}>
<Content ref="content"/>
</Dialog>);
}
}
class Content extends React.Component {
save() {
// Get values from child fields
// and save the content
}
}
I could instead pass a prop (saveOnNextUpdate) down to Content and then execute save whenever it is true, but I would rather figure out how to get the method detailed in the React doc above to work.
Any ideas on how to get the doc approach to work or access the child component function in a different way?
Redux connect accepts an option parametre as the forth parameter. In this option parameter you can set the flag withRef to true. Then you can access functions to refs by using getWrappedInstance(). Like this:
class MyDialog extends React.Component {
save() {
this.refs.content.getWrappedInstance().save();
}
render() {
return (
<Dialog action={this.save.bind(this)}>
<Content ref="content"/>
</Dialog>);
}
}
class Content extends React.Component {
save() { ... }
}
function mapStateToProps(state) { ... }
module.exports = connect(mapStateToProps, null, null, { withRef: true })(Content);
Read more about it here: https://github.com/reactjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options
Worth reading this article about use of refs and consider if there's better approaches: https://facebook.github.io/react/docs/refs-and-the-dom.html#dont-overuse-refs
An alternative way to do this would be to use some other prop name (other than ref). I've found that this also works well if you're using a library like styled-components or emotion For example in a connected MyComponent:
<MyComponent
...
innerRef={(node) => { this.myRef = node; }}
/>
As it turns out, m90 was right -- this was a different issue entirely. I'm posting the solution in case someone runs into the same problem in the future.
My application is built with Redux, and the problem stems from using the react-redux connect function to connect a component to the store/global state. For some reason, exporting a component and connecting it to the store makes it impossible to access the functions inside of it. In order to get around this, I had to remove all use of global state from Content so that I could export it as a "dumb" component.
To be more clear, Content.js looked like this:
var connect = require('react-redux').connect;
class Content extends React.Component {
save() {
// Get values from child fields
// and save the content
// Use of this.props.stateObject
}
}
function mapStateToProps(state) {
const {
stateObject
} = state;
return {
stateObject
};
}
module.exports = connect(mapStateToProps)(Content);
Removing the use of global state (and therefore the use of connect and mapStateToProps allowed me to export the component using:
module.exports = Content;
Accessing this.refs.content.save() magically worked after doing this.

Categories