I'm new to React and I'm trying to pass the HTML element from an onClick event, but I'm not getting the expected result.
Here is the code:
import React, { Component } from 'react';
export class Header extends Component{
isScrolledIntoView (e){
console.log('html element is ',e)
}
render(){
return(
<div>
<button onClick={this.isScrolledIntoView.()}>Click me</button>
</div>
);
}
}
The desired output would be to get the button's HTML element in the console.
You need to capture the target of the e (event) instead of the event itself, like this:
import React, { Component } from 'react';
export class Header extends Component {
isScrolledIntoView (e) {
console.log('html element is ', e.target)
}
render() {
return (
<div>
<button onClick={this.isScrolledIntoView.bind(this)}>Click me</button>
</div>
);
}
}
Here is a demo link: https://codesandbox.io/s/y8xXqopM7
Hope it helps!
The method isScrolledIntoView() is bound to the class, not the component instance, so when you refer to this.isScrolledIntoView() in your render method it will return undefined. Regular React lifecycle methods are bound to the component instance, but for your own custom methods you need to do a little work, you can put it in the constructor:
constructor(props) {
this.isScrolledIntoView = this.isScrolledIntoView.bind(this);
}
Or you can use class properties to auto-bind the method:
isScrolledIntoView = (e) => {
// do stuff
}
2 things you need to change in your code.
1- You have to bind your isScrolledIntoView, and it could be inside your constructor, or doin' this => <button onClick={this.isScrolledIntoView.bind(this)}>Click me</button>
2- You should target your e event instead of only log e you should
=> console.log('html element is ', e.target)
Nice reading for novices in react
Passing current element using ref
class Square extends React.Component {
constructor(props) {
super(props);
this.state = {
value: null,
};
}
render() {
return (
<button className="square"
onClick={function(ref) { console.info(" click : " + ref.target.innerHTML); }}>
{this.props.value}
</button>
);
}
}
Credits : https://stackoverflow.com/ about using "ref"
Related
i want to show my functional component in class base component but it is not working. i made simpletable component which is function based and it is showing only table with some values but i want to show it when i clicked on Show user button.
import React ,{Component} from 'react';
import Button from '#material-ui/core/Button';
import SimpleTable from "../userList/result/result";
class ShowUser extends Component{
constructor(props) {
super(props);
this.userList = this.userList.bind(this);
}
userList = () => {
//console.log('You just clicked a recipe name.');
<SimpleTable/>
}
render() {
return (
<div>
<Button variant="contained" color="primary" onClick={this.userList} >
Show User List
</Button>
</div>
);
}
}
export default ShowUser;
Why your code is not working
SimpleTable has to be rendered, so you need to place it inside the render method. Anything that needs to be rendered inside your component has to be placed there
On Click can just contain SimpleTable, it should be used to change the value of the state variable that controls if or not your component will be shown. How do you expect this to work, you are not rendering the table.
Below is how your code should look like to accomplish what you want :
import React ,{Component} from 'react';
import Button from '#material-ui/core/Button';
import SimpleTable from "../userList/result/result";
class ShowUser extends Component{
constructor(props) {
super(props);
this.state = { showUserList : false }
this.userList = this.userList.bind(this);
}
showUserList = () => {
this.setState({ showUserList : true });
}
render() {
return (
<div>
<Button variant="contained" color="primary" onClick={this.showUserList} >
Show User List
</Button>
{this.state.showUserList ? <SimpleTable/> : null}
</div>
);
}
}
export default ShowUser;
You can also add a hideUserList method for some other click.
Or even better a toggleUserList
this.setState({ showUserList : !this.state.showUserList});
If you're referring to the method userList then it appears that you're assuming there is an implicit return value. Because you're using curly braces you need to explicitly return from the function meaning:
const explicitReturn = () => { 134 };
explicitReturn(); <-- returns undefined
const implicitReturn = () => (134);
implicitReturn(); <-- returns 134
The problem lies with how you are trying to display the SimpleTable component. You are using it inside the userList function, but this is incorrect. Only use React elements inside the render method.
What you can do instead is use a state, to toggle the display of the component. Like this:
const SimpleTable = () => (
<p>SimpleTable</p>
);
class ShowUser extends React.Component {
constructor(props) {
super(props);
this.state = {showSimpleTable: false};
this.toggle= this.toggle.bind(this);
}
toggle = () => {
this.setState(prev => ({showSimpleTable: !prev.showSimpleTable}));
}
render() {
return (
<div>
<button variant = "contained" color = "primary" onClick={this.toggle}>
Show User List
</button>
{this.state.showSimpleTable && <SimpleTable />}
</div>
);
}
}
ReactDOM.render(<ShowUser />, document.getElementById("app"));
<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="app"></div>
The functionality you are looking for is called Conditional Rendering. The onClick prop function is an event handler and events in react may be used to change the state of a component. That state then may be used to render the components. In normal vanilla javascript or jQuery we call a function and modify the actual DOM to manipulate the UI. But React works with a virtual DOM. You can achieve the functionality you are looking for as follows:
class ShowUser extends Component {
constructor(props) {
super(props)
// This state will control whether the simple table renders or not
this.state = {
showTable: false
}
this.userList.bind(this)
}
// Now when this function is called it will set the state showTable to true
// Setting the state in react re-renders the component (calls the render method again)
userList() {
this.setState({ showTable: true })
}
render() {
const { showTable } = this.state
return (
<div>
<Button variant="contained" color="primary" onClick={this.userList}>
Show User List
</Button>
{/* if showTable is true then <SimpleTable /> is rendered if falls nothing is rendered */}
{showTable && <SimpleTable />}
</div>
)
}
}
I have 2 component a parent component to manage the state and a lot of other things and a child component with some reactstrap buttons radio i'm trying to change the state onClick on the child buttons but I get the error: this.setState is not a function and i can't figure out what's wrong with my code =>
//Parent
import React, { Component } from 'react';
import BtnRadio from './btnToggle';
class parent extends Component {
state = {
rSelected: true,
}
onRadioBtnClick(rSelected) {
this.setState({
rSelected:rSelected
});
}
render(){
return (
<div>
<BtnToggle onRadioBtnClick={this.onRadioBtnClick} active={this.state.rSelected}/>
</div>
);
}
};
export default AddAdmin;
//Chlid
import React from 'react';
import { Button, ButtonGroup } from 'reactstrap';
const BtnRadio = (props) => {
return (
<ButtonGroup>
<Button color="light" onClick={() => props.onRadioBtnClick(true)} active={props.active === true}>Enable</Button>
<Button color="light" onClick={() => props.onRadioBtnClick(false)} active={props.active === false}>Disabled</Button>
</ButtonGroup>
);
};
export default BtnRadio;
is there someone who can point me to the right direction i guess that i forgot to bind something...
The problem is, when you're using non-anonymous functions, this gets overridden, and wont refer to the component anymore. Since you're already using class properties, the simple fix, is to keep using the arrow functions, to keep this referencing the component:
onRadioBtnClick = (rSelected) => {
this.setState({
rSelected:rSelected
});
}
See #5 in this medium article, which explains different ways of binding this to keep it referencing the component.
<BtnToggle onRadioBtnClick={() => this.onRadioBtnClick()} active={this.state.rSelected}/>
Arrow function for the rescue.
You should bind the functions your passing like so:
class parent extends Component {
state = {
rSelected: true,
}
onRadioBtnClick(rSelected) {
this.setState({
rSelected:rSelected
});
}
render(){
return (
<div>
<BtnToggle onRadioBtnClick={this.onRadioBtnClick.bind(this)} active={this.state.rSelected}/>
</div>
);
}
}
alternatively, you can bind the functions before passing them in the constructor:
class parent extends Component {
state = {
rSelected: true,
}
constructor() {
super()
this.onRadioBtnClick = this.onRadioBtnClick.bind(this)
}
onRadioBtnClick(rSelected) {
this.setState({
rSelected:rSelected
});
}
render(){
return (
<div>
<BtnToggle onRadioBtnClick={this.onRadioBtnClick} active={this.state.rSelected}/>
</div>
);
}
}
I want to pass a function to Custom Element using ReactJS
ReactJS Component
import React from 'react';
import './SampleComponent';
export class Button extends React.Component {
handleClick = (event) => {
console.log(event)
}
render() {
return (
<div>
<sample-component onclick="handleClick"></sample-component>
</div>
)
}
};
Custom Element
class SampleComponent extends HTMLElement {
static get observedAttributes() {
}
// custom methods
render() {
this.innerHTML = `Custom Element`;
}
// lifecycle hooks
connectedCallback() {
this.render();
}
}
window.customElements.define('sample-component', SampleComponent);
As I understand, when I pass onclick function handleClick JS will search for it in Custom Element implementation (that's why I get an error in console). So how to pass a function? I tried "this.handle" but it also didn't work.
Due to the react Documentation you html should look like this
<sample-component onClick={handleClick}></sample-component>
I'm currently creating a component in react and i'm using the ES Lint rule react/jsx-no-bind. My issue here is that I want to be able to pass a parameter to my components function. Here is the code I would like to use to be able to do so:
class LanguageDropdown extends Component {
constructor(props) {
super(props);
this.state = {};
}
changeLanguage = (lang) => {
console.log(lang)
};
render() {
return (
<div>
{this.props.languages.map(lang => <button onCLick={() => this.changeLanguage(lang)}>{lang}</button>)}
</div>
)
}
...
This pulls up the ESlint error:
JSX props should not use arrow functions
I'm not entirely sure how to achieve this without using an arrow function or using .bind(). I could add a data-attribute to the button element and then just pass in the event into the changeLanguage function and fetch the attribute using event.target() but this doesn't feel like it's the way it should be approached in React.
Can someone tell me what would be the correct way?
You can refactor button into its own component:
class MyButton extends Component {
static propTypes = {
language: PropTypes.string.isRequired,
};
onClick = () => console.log(this.props.language);
render() {
const {language} = this.props;
return (
<button onClick={this.onClick} type="submit">
{language}
</button>);
}
}
and then in your LanguageDropDown class, use MyButton like this:
class LanguageDropdown extends Component {
...
render() {
return (
<div>
{this.props.languages.map(lang => <MyButton key={lang} language={lang}/>)}
</div>
)
}
...
}
A couple of additional things:
You have a typo onCLick should be onClick
You need a key for repeated items
try the below code.
here I tried by taking the value into the state, same can be tried using props.
class LanguageDropdown extends Component {
constructor(props) {
super(props);
this.state = {languages:['telugu','hindi','english']};
// this.changeLanguage = this.changeLanguage.bind(this);
}
changeLanguage(event,lang){
//event.preventDefault();
console.log('change lang: '+JSON.stringify(lang));
};
render() {
return (
<div>
{this.state.languages.map(lang => <button onClick={(event)=>this.changeLanguage(event,lang)}>{lang}</button>)}
</div>
)
}
}
render(<LanguageDropdown />, document.getElementById('root'));
when you bind the handler in the onClick event where you are passing the value to the handler, then we have to pass that value from the event and collect it to get that value.
I encapsulated some HTML code to a extra class and want to hand over a function to it now.
The parent class looks like this:
class Home extends React.Component {
doSomething = id => {
console.log(id);
// here are some fetch operations only available in Home component
};
render() {
return (
<Child doSomething={() => this.doSomething} />
)
}
}
my Child component then looks like this:
const id = 3;
const Child = ({doSomething}) =>
(
<Button onClick={doSomething(id)}>Click</Button>
);
export default Child
I was trying around with different solutions but either I get no result or the onClick function is called when the Home component is rendered instead of when clicking on the button.
I want the function to be executed when the button is clicked. And the id parameter should be handed over as well. I can't have the function in the Child component itself since I have to use some redux actions in it which are not available in the child class.
I know this is not a too difficult question but I'm still a noob with JavaScript..
Edit: I accomplished having the event parameter inside my function but I wonder how to access the id with it. I can't simply add a prop to the Button element since it does not allow that.
Thanks in advance for your help,
Erik
You need to bind method in constructor and pass it to child component
class Home extends React.Component {
constructor() {
this.doSomething = this.doSomething.bind(this);
}
doSomething(id) {
console.log(id);
// here are some fetch operations only available in Home component
}
render() {
return <Child doSomething={this.doSomething} />
}
}
And in Child
const Child = ({doSomething}) =>
(
<Button onClick={() => doSomething(id)}>Click</Button>
)
I think you need something like this:
this.doSomething.bind(this);
It binds this as the first argument of your function, which is needed when you pass a class method as a reference. When doSomething is called in the child component, this will reference the parent component.
First of all your jsx is wrong. Your are missing
render() {
return ...;
}
There is no valid JSX Button
<Button onClick={doSomething(id)}>Click</Button>,
use <button> tag instead.
Here is working example.
const element = <h1>Hello, world</h1>;
class Home extends React.Component {
doSomething = id => {
console.log(id);
// here are some fetch operations only available in Home component
};
render() {
return <Child doSomething={() => this.doSomething('do something input')} />;
}
}
class Child extends React.Component {
constructor(props) {
super(props);
//console.log(props);
}
render() {
return <button onClick={this.props.doSomething.bind(this)}>Click</button>;
}
}
ReactDOM.render(
<Home />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react-dom.js"></script>
<div id="root"></div>
You probably need to pass the id when you are defining the fat arrow function
class Home extends React.Component {
doSomething(id) {
console.log(id);
}
render() {
return <Child doSomething={(id) => this.doSomething(id)} />
}
}
Firstly, in Home component use arrow function as doSomething prop to preserve correct context (alternatively you can use bind in component constructor):
class Home extends React.Component {
doSomething(id) {
console.log(id);
// here are some fetch operations only available in Home component
}
render() {
<Child doSomething={() => this.doSomething()} />
}
}
and then use arrow function that will call passed function with given value as click handler in child component:
<Button onClick={() => doSomething(id)}>Click</Button>