Cannot pass parameter into React handler function - reactjs

I'm new to react and having trouble passing a parameter to a handler function. My test code is as follows:
import React from 'react';
import { useState, useEffect } from 'react';
import './App.css';
function Container(props) {
return <button onClick={props.clickHandler("A")}>Tap</button>;
}
function App() {
function clickHandler(char) {
console.log(char);
}
return <Container clickHandler={clickHandler} />
}
export default App;
When I tap the button nothing happens, no console log. What am I doing wrong here? I have tried handlers without parameters before and they work fine.

Convert Container to this
function Container(props) {
return <button onClick={() => props.clickHandler("A")}>Tap</button>;
}
You need to pass function to onClick but you called it, so you are passing return value of clickHandler which is undefined

first you have to pass the function to the Container component like this:
lets say your Container component is a div like this:
const Container = props => {
return(
<div onClick={props.clickHandler} > your container content here </div>
)
}
export default Container;
this should work :)

You can use the nested arrow function in your hander.
By nesting arrow function, you can add additional params in any steps of your process.
const handled = () => () => () => {}
Try the demo in-text:
function Container(props) {
return <button onClick={props.clickHandler("AAA")}>Tap</button>;
}
function App() {
const clickHandler = value => char => e => {
console.log(value, char, e.target.innerText);
};
return <Container clickHandler={clickHandler(111)} />;
}
ReactDOM.render(<App />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>

Related

Functional component not work inside event

Event triggered but component not work, why?
App.js
import Change from "./Change";
function App() {
return (
<div>
<button onClick={()=><Change/>}>Click here</button>
</div>
);
}
Change.js
const Change=()=>{
return console.log('inside Change.js')
}
export default Change
I know only Change.js also converted to normal function by BABEL.

can we able to specify on click on the component definition itself?

I want to create a component(comp) with onclick event handler. which should be handled by the component itself (i.e. inside the comp.js file).
if I use it inside the parent component we don't need to specify the event but it is handled by the component element(comp element).
is this possible. Any idea to develop this one.
in ParentComponent.js current behavior.
<NewComponent onClick={clickBehaviour}/>
I want like,
In NewComponent.js
const NewComponent.js = ()=>{
// Some code
const clickBehaviour = () =>{
// click behaviour
}
}
Is it possible in the current standards?
why you want to write your onClick event in parent component?
you can do it inside NewComponent.js easily.
just do this:
import React from 'react'
function NewComponent() {
const clickBehaviour = () =>{
// click behaviour
}
return (
<div onClick={clickBehaviour}>
//some jsx here
</div>
)
}
export default NewComponent
and use in anywhere you want to use without onClick event :
< NewComponent />
i cant understand well you situation but you can use forwardRef if you want (also can use old getElementById but using forwardRef is recommended).
import React, { useRef } from "react";
const NewComponent = React.forwardRef((props, ref) => (
<div onClick={() => alert("div 2 clicked")} ref={ref}>
div 2
</div>
));
export default function App() {
const compRef = useRef(null);
return (
<div>
<NewComponent ref={compRef} onClick={() => {
compRef && compRef.current && compRef.current.click();
}} />
</div>
);
}

React function component with functions

Is it possible to create an instance of a function component like regular classes like c# and JAVA where you can call functions on the component? Something like:
https://codesandbox.io/s/hungry-microservice-bp292?file=/src/App.js
It must be an instance so that the component can be used multiple places with its own instance and values. Not like a static class.
import React from "react";
import "./styles.css";
import MyFunc from "./MyFunc";
export default function App() {
const addAlert = () => {
MyFunc.addAlert("dasdsad");
};
return (
<div className="App">
<button onClick={addAlert}>Add alert</button>
<MyFunc />
</div>
);
}
You are mixing different concepts of ReactJS and the underlying DOM. It is not possible to get a ref on the functional component itself. At most you can use forwardRef to get a reference to the underlying DOM element. You can read more about that Refs and the DOM and Forwarding Refs.
With that in mind you could change your approach by uplifting the state to the parent e.g.
App.js
export default function App() {
const [alerts, addAlerts] = useState(["Alert1", "Alert2"]);
const addAlert = () => {
addAlerts(alerts.concat("dasdsad"));
};
return (
<div className="App">
<button onClick={addAlert}>Add alert</button>
<MyFunc alerts={alerts}/>
</div>
);
}
MyFunc.js
const MyFunc = props => {
return (
<>
{props.alerts && props.alerts.map((alert, index) => (
<div>{alert}</div>
))}
</>
);
};
export default MyFunc;

document.getElementById() equivalent in React 2020

I have a component called Button.js that has a button that when clicked i simply would like to know if i am accessing the a div in another component called Timer.js. In vanilla javascript i would simply use document.getElementById() to capture the DOM node. How is this done in React?
I came across callback-refs in the docs but it isn't working. If using a ref isn't the React way of accessing DOM elements please refer me to the best way to do this. thanks in advance.
Button.js
function Button() {
const getHtml = () => {
const node = test.current;
console.log(node);
}
return (
<button onClick={getHtml}>GetHtml</button>
)
}
Timer.js
function Timer() {
const test = useRef(null);
return (
<div ref={test}>... </div>
<Button />
}
I would not use a reference to check if a component is rendered inside of another one.
You could get what you're looking for with createContext and useContext.
(It could work like you tried it. If you'd pass the ref to the button as a prop.)
With the context: You create a TimerContext.Provider in your Timer component and in your button you can check with useContext(TimerContext) if the expected key is in the object. If it's not there then the button is not inside of your Timer.
Please have a look at the snippet below or in the following Codesandbox.
//import React, { useContext, createContext } from "react";
//import "./styles.css";
const { useContext, createContext } = React;
const ContainerContext = createContext({
isInContainer: null
});
const Container = () => {
return (
<ContainerContext.Provider value={{ isInContainer: true }}>
<p>
In container:
<Button />
</p>
</ContainerContext.Provider>
);
};
const Button = () => {
const { isInContainer } = useContext(ContainerContext);
console.log(isInContainer);
const isInside = () => {
alert(isInContainer ? "clicked inside" : "not in container");
};
return <button onClick={isInside}>Click me</button>;
};
function App() {
return (
<div className="App">
<Container />
<Button />
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
rootElement
);
<script crossorigin src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<div id="root"></div>
Update 15.04.2020
The question was not clear to me at first but now I understand the use-case. The idea is to have an Editor component where you're writing markup that can be used to generate a copied snippet view and/or a html markup output.
For this the best is to use a reference to the Editor component and pass it as prop to the preview/output component - it would be also possible with a context but passing it is easier.
Like in the following Sandbox.

how when loading a page to click on a button in react?

how when loading a page to click on a button in react?
I need a button to be pressed when the page loads
https://codesandbox.io/s/gifted-poitras-3sknp
import ReactDOM from "react-dom";
import "./styles.css";
function App() {
return (
<div className="App">
<button onClick={() => alert("loaded")}>button</button>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Are you looking for something like this. Button clicks happens on page load and also when clicked on button?
class App extends React.Component {
constructor(){
super();
this.buttonClicked = this.buttonClicked.bind(this);
}
componentDidMount(){
this.buttonClicked();
}
buttonClicked(){
alert("I'm Clicked");
}
render() {
return (
<button onClick={() => this.buttonClicked()}>
button
</button>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
use useRef to save a reference to the button element combined with useEffect to detect when the component mounts
import React, { useEffect, useRef } from "react";
function App() {
const buttonRef = useRef(null);
useEffect(() => {
buttonRef.current.click();
}, []);
return (
<div className="App">
<button ref={buttonRef} onClick={() => alert("button")}>
button
</button>
</div>
);
}
From React's Hooks API Reference
The function passed to useEffect will run after the render is committed to the screen.
So you can always consider to use useEffect to run whatever side effects do you want right after the page rendered. Make sure to pass [] as the second argument to make sure the arrow function will only be called once.
This is an alternative example of using the useEffect hook with document.getElementById(id) instead of useRef since that has already been mentioned
It is still better to use useRef especially if the component will be reusable in the same page.
import React, {useEffect} from "react";
useEffect(() => {
document.getElementById("btn").click();
},[]);
function App() {
return (
<div className="App">
<button id="btn" onClick={() => alert("loaded")}>button</button>
</div>
);
}

Resources