Set focus in input on clicking div - reactjs

I have the following HTML inside function component
<div>
<input />
<div>
<div>
<input />
<div>
<div>
<input />
<div>
I am not finding any easy way to do this...
I have gone some article saying to store input ref, but here I have confusion about how to store inputref using id or something...
I am totally lost so unable to proceed
Please help
Thanks

you can set id to input and use input to focus on input
example
import React from "react";
import "./styles.css";
export default function App() {
return (
<div className="App">
<div
className='inputCon'
onClick={()=>{
const input = document.getElementById("input");
input.focus()
}}>
<input
placeholder="click on green area"
id="input"
/>
</div>
</div>
);
}

The use of the useRef-Hook is explained in great detail here.
But basically you create a ref and in your onClick you add the call .focus() on it like this:
function CustomTextInput(props) {
// textInput must be declared here so the ref can refer to it
const textInput = useRef(null);
function handleClick() {
textInput.current.focus();
}
return (
<div>
<input
type="text"
ref={textInput} />
<input
type="button"
value="Focus the text input"
onClick={handleClick}
/>
</div>
);
}

You don't necessarily need a ref for that. The following code hooks up directly into the click event, find the closest input child, and focus on it. Click anywhere in the orange zone to focus on the input:
const MyComponent = () => {
const onClick = evt => {
evt.target.querySelector('input').focus();
};
return (<div onClick={onClick}><input/></div>);
}
ReactDOM.render((<MyComponent/>), document.body);
div {
padding: 1em;
background-color: coral;
}
<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>

Related

Updating useState from components

I am learning ReactJS (slowly it seems) and was wondering how the below would work:
I have a search function that the user can enter a word(s) into and it spits out a load of variations of the word entered. The word is put into a button that I would like the user to be able to click and have the whole thing happen again (rather than them having to enter the name in manually).
I can't figure out how to update the useState from the NameList.js file. (I currently get the Error: React Hook "useState" cannot be called at the top level. React Hooks must be called in a React function component or a custom React Hook function) Thanks in advance!
NameList.js
export default function NamesList({ namesList }) {
var names_generated = arrayMaker(generator(split_name(namesList.toString())))
return (
names_generated.map(names_generated => {
return(
<div className="col-4 col-xl-2 col-xxl-1">
<button className="sug-names">{names_generated.name}</button>
</div>
)
})
)
}
Home.js
export default function Home() {
const [namesList, setNamesList] = useState([])
const inputName = useRef()
function getInputName(e){
e.preventDefault();
const name = inputName.current.value
if (name === '') return
setNamesList([name])
}
return (
<>
<div className="d-flex align-items-center justify-content-center">
<div className="">
<Container>
<Form>
<div>
<Form.Control ref={inputName} id="input_name" name="username" type="text" placeholder="Desired Name" />
<Button onClick={getInputName} variant="primary" type="submit"></Button>
</div>
</Form>
</Container>
<Container>
<div className='row'>
<NameList namesList={namesList} />
</div>
</Container>
</div>
</div>
<div>0 Names Found</div>
</>
)
}
I guess it happened because of two things,
The first is that the child should not be in the form of:
“function NamesList(){}”
but rather must be in the form of:
“const NamesList =() =>{}”
and as for the parent, it must be in the form of:
“function home(){}”
and not
“const NamesList = () =>{}”
And the second thing is to try to delete the parentheses like this code:
const NamesList = (namesList) => {
var names_generated = arrayMaker(generator(split_name(namesList.toString())))
return (
names_generated.map(names_generated => {
return(
<div className="col-4 col-xl-2 col-xxl-1">
<button className="sug-names">{names_generated.name}</button>
</div>
)
})
)
}
export default NamesList ;
also edit this function in Home file:
function getInputName(e){
e.preventDefault();
const name = inputName.current.value
if (name === '') return
setNamesList(name)
}

How Can I access a function through props in another component

I have two components Checkout.js and Checklist.js
I have managed to pass data down form checklist to checkout but I have a function to remove item from checkout but i dont know how to access it through props.
How can i Access the removeFood function inside checkout component
My Checklist .js
import React from 'react';
import './componentStyle.css';
function CheckList(props) {
return <div className="checkoutList">
<form>
<div>
<label htmlFor="name">Food</label>
<input type="text" readOnly id='name' value={props.food}></input>
</div>
<div>
<label htmlFor="price">Price</label>
<input type="number" readOnly id='price' value={props.price}></input>
</div>
<div>
<label htmlFor="quantity">Quantity</label>
<input type="number" readOnly id='quantity' value={props.quant}></input>
</div>
<div>
<label htmlFor="total">Total</label>
<input type="number" readOnly id='total' value={props.total}></input>
</div>
</form>
<button style={{
cursor:"pointer"
}} onClick={} type='button'>Remove</button>
</div>;
}
export default CheckList;
My checkout.js
import React from 'react';
import {useState, useEffect} from 'react';
import CheckList from '../components/CheckList';
import Data from '../data.json';
import OrderBtn from '../components/TrayOrderBtn';
function Checkout(props) {
const foodItem = (
Data.myTray.map((item) => <CheckList id={item[Math.random().toString().slice(2)]} key={item.id} food={item['food']} price={item['price']} quant={item['quantity']} />)
)
var [widget, setWidget] = useState(Data.myTray);
const removeFood=(item)=> {
widget.filter((w) => w.id !== item.id)
}
console.log(widget)
useEffect(() => {
setWidget(Data.myTray)
},[widget])
if (Data.myTray.length <= 0) {
return <div>
<h1>Add a Food Item to Your Tray</h1>
</div>
}else {
return <div className="checkout">
{widget.map(
(item) => <CheckList key={item.id} food={item['food']} price={item['price']} quant={item['quantity']} />
)}
<OrderBtn />
</div>;
}
}
export default Checkout;
Take a look at the example below-
Suppose you have a component Checkout and you want to pass your delete function to Checklist component so that you can apply a event listener in Checklist component.
Here we are passing our delete function as a prop to Checklist component
Note: -This is just an example how you can implement.
See our Checkout Component
export default function Checkout(){
const handleDelete=(data)=>{
console.log(data);
}
return(
<Checklist handleDelete={handleDelete}/>
)
}
See our Checklist Component
export default function Checklist(props){
return(
<button onclick={()=>props.handleDelete("your target id or anything")}>Delete</button>
)
}
Here is a minimal reproducible example. The add and remove functions are defined in App and passed down to children components Products and Checkout accordingly. Run the code and click some carrot and banana into your cart. Then click ❌ to remove some.
function App() {
const [cart, setCart] = React.useState([])
const add = item => e =>
setCart([...cart, item])
const remove = index => e =>
setCart([...cart.slice(0, index), ...cart.slice(index+1)])
return <div>
<Products add={add} />
<Checkout cart={cart} remove={remove} />
</div>
}
function Products({ add }) {
const PRODUCTS = ["apple", "banana", "carrot"]
return <div className="products">
{PRODUCTS.map((p, key) =>
<button key={key} type="button" onClick={add(p)} children={p} />
)}
</div>
}
function Checkout({ cart, remove }) {
return <div className="checkout">
{cart.map((c, key) =>
<div>{c} <button type="button" onClick={remove(key)} children="❌"/></div>
)}
</div>
}
ReactDOM.render(<App/>, document.querySelector("#app"))
.products, .checkout { display: flex; flex-direction: flex-row; flex-wrap: wrap; }
.products > button { padding: 0.5rem; margin: 0.5rem; }
.checkout > div { background-color: #CDECFF; padding: 0.5rem; margin: 0.5rem; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>
See Lifting State Up in the React Docs for additional examples.

How to get text of multiple clicked elements using useRef?

I'm trying to get useRef to console.log the text of the clicked element but it just logs the last span element of "Green" every time no matter which span element I click.
Is there a way to console.log the text for the clicked element? Perhaps there's a better hook to get the result I'm looking for?
Thanks for any help.
import React, { useRef } from "react";
export default function Hello() {
const ref = useRef(null);
function checkRef() {
console.log(ref.current.innerText);
}
return (
<div className="container">
<span ref={ref} onClick={checkRef} className="selected">
Blue
</span>
<span ref={ref} onClick={checkRef} className="selected">
Red
</span>
<span ref={ref} onClick={checkRef} className="selected">
Green
</span>
</div>
);
}
If you need a ref, put the <span>s into a separate component:
const Button = ({ text }) => {
const ref = useRef(null);
function checkRef() {
console.log(ref.current.innerText);
}
return (
<span onClick={checkRef} className='selected' ref={ref}>
{text}
</span>
);
};
export default function Hello() {
return (
<Button text='Blue' />
<Button text='Red' />
<Button text='Green' />
);
}
Though, at this point, you could also remove the ref completely and just log the text prop. This would be much more elegant if it's possible with your real code:
function checkRef() {
console.log(text);
}

How to use Tooltip in react-redux

I am new to react.
I want to have a tool tip on the label
The following serves my request
<div class="sds_sp_2xl sds-cb_font--primary">
To see Tooltip positioned on the right,
<a role="button" tabindex="0" aria-describedby="tooltip-cb-02" class="sds-cb_tooltip">
hover over me.
<div role="tooltip" class="sds-cb_tooltip__content sds-cb_tooltip__content--right" id="tooltip-cb-02">Contextual helper text</div>
</a>
</div>
I want to have the tooltip when we hover on the label pertained to checkbox
form
<Field
name='checkMe'
label='check'
component={Checkbox}
checked={checkMe}
{...this.checkboxActions}
/>
checkbox
export const Checkbox = (inputProps) => {
const { input, label, checked } = inputProps
const { name } = input
const className = 'sds-cb_checkbox-a__input'
return (
<label className='sds-cb_checkbox-a' >
<input {...input} className={className} checked={checked} type='checkbox' />
<div className='sds-cb_checkbox-a__box' id={name} />
<span className='sds-cb_checkbox-a__label sds_font-size--14'>{label}</span>
</label>
)
}
How do I embed it to work. So that it would be useful for the fields as well ? Thanks in advance!
Refrence of React-tooltip
This will surely help you.
class Tooltip extends React.Component {
constructor(props) {
super(props)
this.state = {
displayTooltip: false
}
}
hideTooltip=()=>{
this.setState({displayTooltip: false})
}
showTooltip=()=>{
this.setState({displayTooltip: true})
}
render() {
let message = this.props.message
let position = this.props.position
return (
<span className='tooltip'
onMouseLeave={this.hideTooltip}
>
{this.state.displayTooltip &&
<div className={`tooltip-bubble tooltip-${position}`}>
<div className='tooltip-message'>{message}</div>
</div>
}
<span
className='tooltip-trigger'
onMouseOver={this.showTooltip}
>
{this.props.children}
</span>
</span>
)
}
}
class App extends React.Component {
render() {
return (
<div className='container'>
<p>Here is a <Tooltip message={'Hello, I am a super cool
tooltip'} position={'top'}>tooltip</Tooltip> on top.</p>
</div>
)
}
}
ReactDOM.render(
<App />,
document.getElementById('app')
)
First off you should not wrap the label around the input element but set the for attribute to the correct id of the input. So when clicking the label the input gets focused. And to show a tooltip or start any other action use the standard javascript events onMouseEnter and onMouseLeave, set some state according to this and use this state as conditional rendering of the tooltip element:
<label for="someId" onMouseEnter={()=>this.setState({showTooltip:true})} onMouseLeave={()=>this.setState({showTooltip:false})}>Labeltext</label>
<input id="someId" .../>
{this.state.showTooltip && <div>Tooltip</div>}
This will also work when you're setting and using some redux state.

How to push values into state by calling single onChange function - react

I am new to reactive. I am working on react+flux+alt with ES6.
I have a form for creating new record.
Component
import React from 'react';
import { Input, Button, Glyphicon, ButtonToolbar } from 'react-bootstrap';
import AttributeSectionStore from 'stores/attributeSection/AttributeSectionStore';
import TextBoxesSet from '../descriptionTextBoxes';
import styles from 'scss/_common';
export default class AttributeSection extends React.Component {
constructor(props) {
super(props);
}
_onCreate = () => {
console.log('___________', this.state);
}
onChangeName = (evt) => {
this.setState({name: evt.target.value});
};
onChangeRank = (evt) => {
this.setState({rank: evt.target.value});
};
static getPropsFromStores() {
return recordStore.getState();
}
render() {
return (
<div className="container">
<div className={styles.mainheader}>
<h2 >New Record</h2>
</div>
<div className="col-md-9">
<form className="form-horizontal">
<div className="row">
<div className="col-md-12">
<Input type="text" label="Name" labelClassName="col-xs-2"
wrapperClassName="col-xs-4" value={this.props.name}
onChange={this.onChangeName}/>
</div>
</div>
<div className="row">
<div className="col-md-12">
<Input type="number" label="Rank" labelClassName="col-xs-2"
wrapperClassName="col-xs-4" value={this.props.rank}
onChange={this.onChangeRank}/>
</div>
</div>
<div className="row">
<div className="col-md-4 col-md-offset-2">
<ButtonToolbar className={styles.formBtnGrp}>
<Button bsStyle="primary" onClick={this._onCreate}>Create</Button>
<Button type="reset">Cancel</Button>
</ButtonToolbar>
</div>
</div>
</form>
</div>
</div>
);
}
}
AttributeSection.propTypes = {
name: React.PropTypes.string
rank: React.PropTypes.number
};
Using above component now I'm getting data into state but form may have more than 2 fields. I'm using two functions to update state instead of that how can use single function to update state object?Is there any other best practice is there?
The most common pattern to solve this is using bind() to curry a value to the onchange callback. This is was #knowbody referenced (React.js: Identifying different inputs with one onChange handler)
An alternate, but similar, pattern is adding a second tag within the element to identify the name of the state property to change. I'll show an example using label from your code (obviously you want to use a dedicated tag since label is for display and would be localized).
onInputChanged(evt) {
var newState = this.state,
propName = evt.target.label.toLowerCase();
newState[propName] = evt.target.value;
this.setState(newState);
};

Resources