react.js how can I autofocus a contentEditable element - reactjs

How can I set focus on a contentEditable element in react?
I have found a lot pages anout the subjet, but cant get it to work.
Sample code:
import React, { useRef, useEffect } from 'react';
const About = () => {
const inputRef = useRef(null);
useEffect(inputRef => {
if (inputRef) {
inputRef.focus();
}
}, []);
return (
<div className="about">
<h2>About</h2>
<p className="paragraph"
contentEditable={true}
suppressContentEditableWarning={true}
spellCheck={false}
ref={inputRef}
>
Hello
</p>
</div >
)
}
export default About;

Looks like my solution is this.
import React, { useRef, useEffect } from 'react';
const About = () => {
const inputRef = useRef(null);
useEffect(() => {
inputRef.current.focus();
}, [inputRef]);
return (
<div className="about">
<h2>About</h2>
<p className="paragraph"
contentEditable={true}
suppressContentEditableWarning={true}
spellCheck={false}
ref={inputRef}
>
Hello
</p>
</div >
)
}
export default About;

May be you can use this:
<textarea className="paragraph"
ref={inputRef}
value={yourValueState}
autofocus/>

Found another working solution:
const inputRef = useCallback(node => {
node.focus()
}, [])

Related

How to display the current data and previous data entered via form in react

Thanks for the help in advance. Currently, I am learning react. As a part of learning, I'm working on a basic expense listing app. In it, I was able to list the data entered through the form. But the problem is that when the new data is entered the previous one gets disappeared. I want to list the current as well as the previous data. Can anyone help me to resolve this.
App.js
import React, { useState, Fragment } from "react";
import ExpenseAddForm from "./ExpenseAddForm/ExpenseAddform";
import ExpenseList from "./ExpenseList/ExpenseList";
const App = () => {
const [expensesData, setExpensesData] = useState("");
const FormData = (datas) => {
setExpensesData(datas);
};
return (
<Fragment>
<div className="new-expense">
<ExpenseAddForm FormData={FormData} />
</div>
<ExpenseList listDatas={expensesData}></ExpenseList>
</Fragment>
);
};
export default App;
ExpenseAddform.js
import React, { useState } from "react";
import "./ExpenseAddForm.css";
const ExpenseAddForm = (props) => {
const [title, setTitle] = useState("");
const [amount, setAmount] = useState("");
const [date, setDate] = useState("");
const titleHandler = (e) => {
setTitle(e.target.value);
};
const amountHandler = (e) => {
setAmount(e.target.value);
};
const dateHandler = (e) => {
setDate(e.target.value);
};
const formSubmitHandler = (event) => {
event.preventDefault();
const formData = {
title: title,
amount: amount,
date: date,
};
props.FormData(formData);
setTitle("");
setAmount("");
setDate("");
};
return (
<form onSubmit={formSubmitHandler}>
<div className="new-expense__controls">
<div className="new-expense__control">
<label>Title</label>
<input type="text" onChange={titleHandler} value={title} />
</div>
<div className="new-expense__control">
<label>Amount</label>
<input type="number" onChange={amountHandler} value={amount} />
</div>
<div className="new-expense__control">
<label>Date</label>
<input type="date" onChange={dateHandler} value={date} />
</div>
</div>
<div className="new-expense__actions">
<button type="submit">Cancel</button>
<button type="submit">Add Expense</button>
</div>
</form>
);
};
export default ExpenseAddForm;
ExpenseList.js
import React from "react";
import ExpenseItem from "./ExpenseItem/ExpenseItem";
import ExpenseDateFilter from "./ExpenseDateFilter/ExpenseDateFilter";
import "./ExpenseList.css";
const ExpenseList = (props) => {
return (
<div className="expenses">
<ExpenseDateFilter />
<ExpenseItem expenseInfos={props.listDatas} />
</div>
);
};
export default ExpenseList;
ExpenseItem.js
import React from "react";
// import ExpenseDate from "../ExpenseDate/ExpenseDate";
import "./ExpenseItem.css";
const ExpenseItem = (props) => {
return (
<div className="expense-item">
{/* <ExpenseDate enteredDate={props.expenseInfos.date} /> */}
<div className="expense-item__description">
<h2>{props.expenseInfos.title}</h2>
{/* <div className="expense-item__price">${props.expenseInfos.amount}</div> */}
</div>
</div>
);
};
export default ExpenseItem;
ExpenseDateFilter.js
import React from "react";
const ExpenseDateFilter = () => {
return (
<div className="expenses-filter">
<div className="expenses-filter__control">
<label>Filter by year</label>
<select>
<option value="2022">2022</option>
<option value="2021">2021</option>
<option value="2020">2020</option>
<option value="2019">2019</option>
</select>
</div>
</div>
);
};
export default ExpenseDateFilter;
The problem with your code is on each submit your overriding the expensesData with the new data
instead you need to do
const FormData = (datas) => {
setExpensesData([...expensesData,datas]);
};
now you have list of data next you need to handle multiple expenses data in ExpenseList.js
{props.listDatas.map((data,key)=>
<ExpenseItem expenseInfos={data} />
)}
and it should be done here is a link of a working example https://codesandbox.io/s/xenodochial-grass-g2k1fh?file=/src/App.js:467-476

Not able to focus on input when i use useImperativeHandle

Here is my code: I have created the input component and header component. if I comment on the useImperativeHandle hook, input focus is working fine. please check this code.
import { forwardRef, useImperativeHandle, useRef } from "react";
const Input = forwardRef((props, ref) => {
// here is useImperativeHandle
useImperativeHandle(ref, () => ({
// ```method```
someExposedProperty: () => {
alert("inside the exposed property function!");
}
}));
// Return statement
return (
<>
<input type="text" ref={ref} />
</>
);
});
// header component
export default function Header() {
const inputRef = useRef();
return (
<>
<div className="container">
<Input ref={inputRef} />
</div>
<button
// Click function.
onClick={() => {
inputRef.current.focus();
}}
>
Add focus
</button>
</>
);
}
You need two refs here. One to bind the functions (which are going to expose to the outside) and another to keep a reference to the input element (this one is only used inside the Input and not exposed to outside components).
Try like below:
import { forwardRef, useImperativeHandle, useRef } from "react";
const Input = forwardRef((props, ref) => {
const inputRef = useRef();
useImperativeHandle(
ref,
() => ({
focus: () => {
inputRef.current.focus();
}
}),
[]
);
return (
<>
<input type="text" ref={inputRef} />
</>
);
});
export default function Header() {
const inputRef = useRef();
return (
<>
<div className="container">
<Input ref={inputRef} />
</div>
<button
onClick={() => {
inputRef.current.focus();
}}
>
Add focus
</button>
</>
);
}
Working Demo

Focus the Input automaticly in a react way every time I refresh the page

I can focus the input by get the element By ID, but is there a standard react way to do it?
function App() {
useEffect(() => {
let myInput = document.getElementById('myInput');
myInput.focus()
})
return (
<div className="App">
<input id="myInput" placeholder='your name'/>
</div>
);
}
Using useRef you can do it !
import React, { useEffect, useRef } from "react";
function App() {
const inputTxt = useRef(null)
useEffect(() => {
inputTxt.current.focus()
})
return (
<div>
<input type='text' />
<input ref={inputTxt} />
</div>
);
}
export default App;
We should never get DOM elements as these references might later give rise to memory leaks.
You could create a ref object and pass it to the input component and then use it later.
For example:
function App() {
const inputRef = React.useRef<HTMLElement>(null);
useEffect(() => {
inputRef.current.focus();
})
return (
<div className="App">
<input id="myInput" placeholder='your name' ref={inputRef}/>
</div>
);
}
Please read this doc for further information:
https://reactjs.org/docs/refs-and-the-dom.html

how to get input value of a json data when submitted

I have json data file. I want to make a search with the names of the data and display the typed names when I click the search button.
I get the value of input in the console when I type something however I am not able to display it on the screen
How can I display the value of this input ?
my code is below
PostResults.jsx
import React from "react";
const PostResults = (props) => {
const {name} = props.posts
return(
<div className="">
<p className="titles">{name}</p>
</div>
)
}
export default PostResults
Posts.jsx
import React, { useState, useEffect } from "react";
import PostResults from './PostResults'
const Posts = (props) => {
const [posts, setPosts] = useState([]);
const [searchTerm,setSearchTerm]=useState([]);
const getData = () => {
fetch('data.json')
.then(response => {
return response.json()
//console.log(response)
})
.then(data => {
setPosts(data)
console.log(data)
})
}
useEffect(() => {
getData()
},[])
const submitHandler = (event) => {
event.preventDefault()
{searchTerm ? searchTerm : console.log("none")}
}
return(
<div className="">
<input
type="text"
placeholder="Search Anything"
name="query"
onChange={e => setSearchTerm(e.target.value)}
className="search-input"
/>
<button
onClick={submitHandler}
type="submit"
className="search-button"
>
<i className="fas fa-search"></i>
</button>
{posts.map(posts => (
<PostResults key={posts.id} posts={posts}/>
))}
</div>
)
}
export default Posts
App.jsx
import React from "react";
import "./style.css";
import 'bootstrap/dist/css/bootstrap.min.css'
import Posts from './components/Posts'
export default function App() {
return (
<div className="container">
<div className="row">
< Posts />
</div>
</div>
);
}

React - simple ul li filter

I am new to React and I am trying to filter a list of emails in .users-list. I just want to return what the user is typing on the SearchBox but it does not work. Any suggestions?
Dashboard.js
import React, { Component } from "react";
import Button from "../Button/Button";
import SearchBox from "../SearchBox/SearchBox";
import "./Dashboard.css";
import fire from "../../fire"
class Dashboard extends Component {
constructor(){
super();
this.state = {
users:[],
searchField:''
}
}
handleLogout = () => {
fire.auth().signOut();
};
render() {
const {users, searchField} = this.state
const filteredUsers = users.filter(users => (users.users.toLowerCase.inc))
return (
<div>
<h2>Welcome</h2>
<button onClick={this.handleLogout}>Logout</button>
<div className="users-container">
<div>
<SearchBox
placeholder="Enter email..."
handleChange={(e) =>
this.setState({ searchField: e.target.value})
}
/>
</div>
<ul className="users-list">
<li>
<span>jean#gmail.com</span>
</li>
<li>
<span>albert#gmail.com</span>
</li>
<li>
<span>kevin#gmail.com</span>
</li>
<li>
<span>lucie#gmail.com</span>
</li>
</ul>
</div>
</div>
);
}
}
export default Dashboard;
SearchBox.js
import React from 'react';
const SearchBox = (props) => {
return(
<input
type='search'
className='search'
placeholder={props.placeholder}
onChange={props.handleChange}
/>
)
}
export default SearchBox
You can follow: codesandbox DEMO
For optimize performance:
useMemo will only recompute the memoized value when one of the dependencies has changed. This optimization helps to avoid expensive calculations on every render.
import React, { useMemo, useState } from "react";
import "./styles.css";
const usersData = [
{id:1,email: 'jean#gmail.com'},
{id:2,email: 'albert#gmail.com'},
{id:3,email: 'kevin#gmail.com'},
]
export default function App() {
const [search, setSearch] = useState("");
const filteredUsers = useMemo(() => {
if (search) {
return usersData.filter(
(item) =>
item.email
.toLowerCase()
.indexOf(search.toLocaleLowerCase()) > -1
);
}
return usersData;
}, [search]);
return (
<div className="App">
<h1>users list</h1>
<input type="search" name="search" value={search} onChange={e => setSearch(e.target.value)} />
<ul>
{filteredUsers.length > 0 ?
(filteredUsers && filteredUsers.map(item => (
<li key={item.id}>{item.email}</li>
))): <div>empty</div>
}
</ul>
</div>
);
}

Resources