Reactjs function invoking on page load before onClick event - reactjs

Function working while the page load my code as follow
Parent
import React, { Component } from "react";
import ExtnButton from "./Button";
class MovieList extends Component {
handleDelete = index => {
console.log("inside handleDelete:");
};
render() {
return (
<React.Fragment>
<ExtnButton handleDelete={this.handleDelete} index={index} />
</React.Fragment>
);
}
}
export default MovieList;
Child
import React, { Component } from "react";
class Button extends Component {
state = {};
render() {
return (
<button
onClick={this.props.handleDelete(this.props.index)}
className="btn btn-danger"
>
Delete
</button>
);
}
}
export default Button;
But on page loading the function handleDelete invoking without any click event

Wrong:
onClick={this.props.handleDelete(this.props.index)}
Correct:
onClick={() => this.props.handleDelete(this.props.index)}

It's because you're calling the method inside the onClick event directly. There are three approaches to bind the events with the parameters:
Using inline arrow function:
onClick={() => this.props.handleDelete(this.props.index)}
Using public class method (as you also have currently), but just need to curry:
handleDelete = index => () => {
console.log("inside handleDelete:");
};
Using bound method:
handleDelete(index) {...}
But for this, you need to bind the this inside the constructor.
this.handleDelete = this.handleDelete.bind(this)
If you need to pass the event:
(using inline arrow function)
onClick={(e) => this.props.handleDelete(this.props.index, e)}
(using public class method)
handleDelete = index => e => {
console.log(e);
};
Notice that if you use inline arrow function, then you don't need to curry the function. This will be just fine:
handleDelete = index => {...}
Or, without using public class method (ie. bound method):
handleDelete(index) {...}

Related

Use state from a Context inside Class component

here is my Codepen which illustrates my current problem:
I woud like to use the class component, so I can call the forward function from parentComponents (through ref), but I currently cant figure out how to manipulate the context (Where the current state of the application is stored.
Can somebody help me ?
https://codesandbox.io/s/gallant-dust-vtp46?file=/src/App.tsx:0-1918
Kind regards
I don't know the exactly answer, but I have a solution, that you can forward function to parent component with Functional component. Check this code:
import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react';
const ChildComponent(props, ref) => {
useImperativeHandle(ref, () => {
const funcCallFromParent = (params) => {
funcToHandle(params);
};
return { funcCallFromParent };
});
const doSomething(params) {
...
}
...
}
and then call if from your ParentComponent
...
childRef.current.funcCallFromParent(params);
...
This way will help you use Functional Component instead of Class Component, therefore easier to access the context.
Additional, maybe you'll want to try Redux, it's a good and most popular Context Management for ReactJS.
To consume React Context with class-based component you wrap them with the Consumer component and inject context value as props.
SStateButton
export class SStateButton extends Component {
refe;
name;
onclick;
constructor({
refe,
name,
onclick
}: {
refe: Status;
name: string;
onclick: any;
}) {
super({ refe, name, onclick });
this.refe = refe;
this.name = name;
this.onclick = onclick;
}
forwardToStatus = () => {
if (this.onclick) {
this.onclick(this.refe);
}
};
render() {
return (
<button
className="btn btn-light btn-outline-dark"
onClick={this.forwardToStatus}
>
ClassComponent {this.name}
</button>
);
}
}
App - Given context value value={[status, setStatus]}
<StateContext.Consumer>
{([, setStatus]) => (
<SStateButton
refe="1 Page"
name="Go to Page 1"
onclick={(val) => {
console.log("Additional functions added");
setStatus(val);
}}
/>
)}
</StateContext.Consumer>
Since SStateButton is being used in the same component that is providing the context value, and has the status state and updater function already in scope, the setStatus callback can also just be enclosed in the onclick callback and work just the same.
<SStateButton
refe="1 Page"
name="Go to Page 1"
onclick={(val) => {
console.log("Additional functions added");
setStatus(val);
}}
/>

Pass 'this' object to component - Typescript / React

I'd like to call a public method from the FirstComponent in my OtherComponent. However, I'm seeing this error:
"TypeError: firstCompObj.foo() is not a function" when I click the "Submit" button. After doing some debugging, the firstCompObj isn't showing up as type FirstComponent, but as an empty object.
I know that technically "foo" is a method, not a function, but what is the difference, and is it possible to call this method from the OtherComponent? Can I pass an object like this using the "this" keyword?
"FirstComponent.tsx":
export class FirstComponent: extends React.Component<{}, {}> {
..
public foo() {
// do something
}
private _otherComonent = (): JSX.Element => {
return (
<Other firstComponentObj={this} />
);
};
}
"otherfile.tsx":
export const Other: Component = (firstCompObj: FirstComponent) => {
...
<Button text='Submit' onClick={() => {firstCompObj.foo();}} />
...
}
You want to pass a function that calls foo() rather than passing the whole FirstComponent.
Other isn't actually a component right now because it doesn't take a props object. Lets make it accept the prop doFoo which is a function that requires no arguments and returns nothing.
interface OtherProps {
doFoo: () => void;
}
export const Other: React.FC<OtherProps> = ({ doFoo }) => {
return <button onClick={doFoo}>Submit</button>;
};
We we call Other in the render method of FirstComponent, we provide that doFoo prop. It will be an anonymous function that calls this.foo on the FirstComponent instance. The arrow => binds the this context.
export class FirstComponent extends React.Component<{}, {}> {
foo() {
// do something
console.log("called foo from FirstComponent");
}
render() {
return (
<div>
<p>There might be some content here</p>
<Other doFoo={() => this.foo()} />
</div>
);
}
}
FirstComponent could easily be a function component instead of a class component, but I'm keeping it the way that you had it.

Calling React function from stencil web component

This is my react functional component
const goTo = () => {
console.log("This method call.");
};
return (
<div>
<div className="container">
<otp-web-component
callBack={() => goTo}>
</otp-web-component>
</div>
</div>
)
This is stencil component
#Component({
tag: "otp-web-component",
styleUrl: "my-component.css",
})
export class otpcomponent {
#Method() CallBack:()=>void; //calling this on button click
#Listen("event.keydown.enter")
goBack() {
// calling callback function here
}
render(){
return(
<button
class="btn btn-primary"
style={buttonStyle}
onClick={this.goBack.bind(this)}
>
get
</button>
)
}
When clicking on get button in stencil component it should execute the react function goTo();
Just listing some things that look wrong and might help you figure out what the problem is:
You're using the #Method decorator for CallBack but you're not defining a method. You probably want to use the #Prop decorator. It's possible to pass a function (or any JS object) as a prop. You can read about the method decorator here: https://stenciljs.com/docs/methods.
When using your component in React, you're not actually calling the goTo function. You're passing a function that returns the goTo function instead because you forgot the (). You either want to use callBack={goTo} or callBack={() => goTo()}.
You've defined your prop (the one with the #Method decorator) as CallBack (pascal case) but then you're using it as callBack (camel case). Stencil component property names are not case insensitive.
#Listen("event.keydown.enter") this is not how you bind an event listener to a keyboard event. See https://stenciljs.com/docs/events#keyboard-events.
So, I think your component should look sth like this (simplified):
#Component({ tag: 'otp-web-component' })
export class OtpWebComponent {
#Prop() callback: () => void;
goBack = () => {
// ...
this.callback();
}
render() {
return <button onClick={this.goBack}>Click me</button>;
}
}
and then you can use it like
export default () => {
const goTo = () => console.log('I got called');
return <otp-web-component callback={goTo} />;
}

I passed a function from parent to child, implemented it onClick on the child. Getting Error: this.props.function() is not a function

I passed a function from parent to child and implemented it onClick on the child. While clicking the button, I get the error:
this.props.function() is not a function.
/* PARENT */
class User extends React.Component {
buttonClicked(page)
{
this.setState({ page }, () => console.log(`NEW STATE`, this.state));
}
render()
{
return (
<Toolbar buttonClicked={page => this.buttonClicked(page)}/>
)
}
}
/* CHILD */
class Toolbar extends React.Component {
render()
{
let page = 3;
return (
<button value={page} onClick={page=> this.props.buttonClicked(e.target.value)}>
{page}
</button>
)
}
}
Error: bundle.js:34689 Uncaught TypeError: _this2.props.buttonClicked
is not a function at onClick (bundle.js:34689)
Declare your buttonClicked() with lexical binding through arrow function. Alternatively, you can bind the function in constructor.
And you access e.target.value from there:
buttonClicked = e => {
const page = e.target.value
// do your setState
}
You should pass down the function reference as props like this:
<Toolbar buttonClicked={buttonClicked}/>
In child component:
<button value={page} onClick={this.props.buttonClicked}>
{page}
</button>
Notice that we are merely passing down the reference of buttonClick() function, not calling. Only when the button is clicked, the function get called with event e, and we can then access e.target.value.
Read more about event handling in React here
You need to bind this value of the buttonClicked function to this of the parent. In your parent write this,
constructor(props) {
super()
this.buttonClicked = this.buttonClicked.bind(this)
}
The issue is not about the function but event e that is undefined when you use arrow function onClick={page => this.props.buttonClicked(e.target.value)}
class User extends React.Component {
buttonClicked(page) {
this.setState({ page }, () => console.log(`NEW STATE`, this.state));
}
render() {
return (
<Toolbar buttonClicked={page => this.buttonClicked(page)} />
)
}
}
/* CHILD */
class Toolbar extends React.Component {
render() {
let page = 3;
return (
<button value={page} onClick={e => this.props.buttonClicked(e.target.value)}>
{page}
</button>
)
}
}
render(<User />, document.getElementById('root'));
CodeSandbox

How to call a function which is inside a class in React?

How can i call a function which is inside a class ?
here is the code -
class FriendList extends Component {
demoFunction()
{
console.log('Inside demo function')
}
render(){
<div>Hello</div>
}
}
const button= () => {
return (
<button onClick={() => demoFunction()}>Button</button>//How can i call demo function here?
);
}
I don't understand what are you trying to do by calling a function of a React Component from another component. I strictly feel you are on the wrong track. But still if want to do that, you can do like this:
class FriendList extends Component {
static demoFunction() {
console.log('Inside demo function')
}
render() {
<div>Hello</div>
}
}
const button = () => {
return (
<button onClick={() => FriendList.demoFunction()}>Button</button>
)
}
Just declare demoFunction as static function and call this with the help of class name i.e FriendList.demoFunction()

Resources