Undefined 'this' when handing class method to React component - javascript

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

Related

How can I reuse a function with this.setState and other component function in react native?

I don't want to have a handle refresh function in every single screen in my project, so I created a Helper.js to handle this. This function has this.setState and another call for a function inside the screen component. This is what I got so far but it returns an error.
Exported function
export function handleRefresh(component) {
const {page, refreshing} = component.state
component.setState(
{
page:1,
refreshing:true
},
() => {
component.makeRemoteRequest();
}
);
};
and I call it in the component like this:
<FlatList
...
onRefresh={()=> handleRefresh(this)}
refreshing={this.state.refreshing}
...
/>
I saw that you can pass "this" as a param, but the error still says it is undefined.
setState shall be within that screen always where you are using FlatList because after making API you have to update and control the state of that screen.
All the states will be in the component where FlatList using.
Use case are not logical in my view. You can try to create a helper function which accepts different functions params like: page, isRefreshing and return the API response and also the API url and datapost will also be dynamic. Because you want to use it in many areas. It will be difficult to maintain.
So, If you like then use redux what you want.
https://snack.expo.io/#prashen/flatlist-onrefresh
You can do in this way.
class AComponent {
...
render() {
const thisComponent = this;
<FlatList
...
onRefresh={()=> handleRefresh(thisComponent)}
refreshing={this.state.refreshing}
...
/>
}
};
All this. uses refer a same class or function. Only use IF i'ts a child function, component or method.
I'ts don't work out of class function original, you can make a bridge for share data or status.
You can use redux for it and using stores for update screen state.

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?

What's the purpose of using classes in React?

I mostly see JavaScript use classes as a constructor as following:
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
// Getter
get area() {
return this.calcArea();
}
// Method
calcArea() {
return this.height * this.width;
}
}
What's the reason React uses classes without using the contructor() function, such as following? I don't see classes being used to create instances.
class App extends Component {
render() {
return (
<div className="app-content">
</div>
)
}
}
Right now you should use classes in React if you need to use "advanced" component lifecycle methods like shouldComponentUpdate() or such.
Previously class components were used to handle local state in them. Right now we have Hooks API which allows to use state in a more elegant way and without need of class components.
If you want more details, you can read the article by Dan Abramov: How Are Function Components Different from Classes?.
Regardless your example, you're right, this code:
class App extends Component {
render() {
return (
<div className="app-content">
</div>
)
}
}
can be written as:
function App() {
return <div className="app-content"></div>
}
What's the reason React uses classes without using the contructor() function
From the JavaScript class doc:
If you do not specify a constructor method, a default constructor is used.
So a constructor exists for every class whether a constructor method is specified or not.
I don't see classes being used to create instances.
React components implemented as classes get instantiated by React as part of the rendering process.
Specifically, in the new React Fiber creating an instance of a React class component happens on this line of the source code.
But yes, #vicondin is right that the simple component from the question can be implemented as a function component, that class components used to be the only way to maintain state, implement lifecycle methods, etc., and that the new Hooks makes it possible to...
use state and other React features without writing a class.
In React, state is used in a React class component. There you can set initial state in the constructor of the class, but also access and update it with this.state and this.setState, because you have access to the class instance by using the this object.
If you use class in React component, even without using constructor() you can set initial state like below:
class App extends Component {
state = {
hello: 'Hello'
};
onClickHello = value => {
this.setState({ hello: 'Why did you clicked?' });
};
render() {
return (
<div className="app-content" onClick={this.onClickHello}>
{this.state.hello}
</div>
)
}
}
Another advantage is you can make use of all the React lifecycle methods
Update: After React16, you can use the lifecycle events even in function components using react hooks
Also biggest reason is the handling of state and lifecycle(componendDidMount ..etc) , class can do everything functions can , but at the cost of readability and statelessness . But in the most cases I rarely use classes only if I need a complex parent component with lifecycle

Call a static function into the class React ES6

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.

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