Typescript: How to update the state - reactjs

In my project, I have an email field to implement using the chip component. But I am facing a problem here, first time, when I paste multiple email values it gets inserted into the field, but second time when I copy some other values and paste them into the field, it replaces the previous values.
In first time:
Secnod time when I paste "abc4#abc.com" :
previous values replace with the current value.
import Chip from "#material-ui/core/Chip";
import TextField from "#material-ui/core/TextField";
import React, { useRef, useState } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
export const TagActions = () => {
const [items, setItem] = useState<string[]>([]);
const [value, setValue] = useState("");
const [error, setError] = useState("");
const divRef = useRef<HTMLDivElement>(null);
const [flag, setFlag] = useState(false);
const handleDelete = (item: any) => {
console.log("handleDelete", item);
const result = items.filter((i) => i !== item);
setItem(result);
};
const handleItemEdit = (item: any) => {
console.log("handleItemEdit", item);
const result = items.filter((i) => i !== item);
setItem(result);
setValue(item);
console.log("value", value);
};
const handleKeyDown = (evt: any) => {
if (["Enter", "Tab", ","].includes(evt.key)) {
evt.preventDefault();
var test = value.trim();
if (test && isValid(test)) {
items.push(test);
setValue("");
}
}
};
const isValid = (email: any) => {
let error = null;
if (isInList(email)) {
error = `${email} has already been added.`;
}
if (!isEmail(email)) {
setFlag(true);
// error = `${email} is not a valid email address.`;
}
if (error) {
setError(error);
return false;
}
return true;
};
const isInList = (email: any) => {
return items.includes(email);
};
const isEmail = (email: any) => {
return /[\w\d\.-]+#[\w\d\.-]+\.[\w\d\.-]+/.test(email);
};
const handleChange = (evt: any) => {
setValue(evt.target.value);
// setError("")
};
const handlePaste = (evt: any) => {
evt.preventDefault();
var paste = evt.clipboardData.getData("text");
console.log("pppp", paste);
var emails = paste.match(/[\w\d\.-]+#[\w\d\.-]+\.[\w\d\.-]+/g);
if (emails) {
console.log("inside if", emails);
var toBeAdded = emails.filter((email: any) => !isInList(email));
setItem(toBeAdded);
}
};
return (
<>
<div>
<TextField
id="outlined-basic"
variant="outlined"
InputProps={{
startAdornment: items.map((item) => (
<Chip
className={!isEmail(item) ? "chip-tag-error" : "chip-tag"}
key={item}
tabIndex={-1}
label={item}
onDelete={() => handleDelete(item)}
onClick={() => handleItemEdit(item)}
/>
)),
}}
ref={divRef}
value={value}
placeholder="Type or paste email addresses and press `Enter`..."
onKeyDown={(e) => handleKeyDown(e)}
onChange={(e) => handleChange(e)}
onPaste={(e) => handlePaste(e)}
/>
</div>
{error && <p className="error">{error}</p>}
</>
);
};
I am a beginner in react typescript. Please give me a solution to solve this situation.

Append to the list instead of overwriting it like
setItem(i => [...i, ...toBeAdded]);

Related

React draggable not clicking at once

I'm making a puzzle game with React. I am trying to use the "draggable" function, but there is a phenomenon that it does not click at once and requires several times to work.
It doesn't seem to be a mouse problem.
Below is the code. I don't know which one is the problem.
board.tsx
const Board = () => {
const {blocks, handleSwap} = useBlocks();
const [hydrated, setHydrated] = useState(false);
const [grabItem, setGrabItem] = useState("");
useEffect(() => {
setHydrated(true);
}, []);
return (
<>
{hydrated && (
<StyledBoard>
{blocks.map((row) =>
row.map((block) => (
<Block
key={uuid()}
id={block.index}
color={block.color}
handleSwap={handleSwap}
grabItem={grabItem}
setGrabItem={setGrabItem}
/>
))
)}
</StyledBoard>
)}
</>
);
};
export default Board;
subcomponent
block.tsx
import styled from "styled-components";
const Block = ({id, color, handleSwap, grabItem, setGrabItem}: IBlockProps) => {
const [isDragging, setIsDragging] = useState(false);
const [isDragOver, setIsDragOver] = useState(false);
const handleDragStart = (e: React.DragEvent<HTMLElement>) => {
setIsDragging(true);
setGrabItem(e.currentTarget.id);
};
const handleDragOver = (e: React.DragEvent<HTMLElement>) => {
e.preventDefault();
setIsDragOver(true);
};
const handleDragLeave = (e: React.DragEvent<HTMLElement>) => {
e.preventDefault();
setIsDragOver(false);
};
const handleDrop = (e: React.DragEvent<HTMLElement>) => {
e.preventDefault();
setIsDragging(false);
setIsDragOver(false);
handleSwap(grabItem, e.currentTarget.id);
};
return (
<StyledBlock
onDragStart={handleDragStart}
onDrop={handleDrop}
onDragOver={handleDragOver}
onDragLeave={handleDragLeave}
id={id}
isDragOver={isDragOver}
color={color}
/>
);
};
export default Block;

useState and useRef don't work together properly

I'm in a case where I need to combine useState and useRef in a way, but I'm having a problem when it comes to deleting, so for example when I call the delete the update function firstly I update the state and then update the user jeff, but the deleted item firstly is deleted from the iterated and showing list, then again pop-ups, but kinda messed, the content is not the same.
Here is how I manage delete:
const Delete = (props: any, index: number, editorsRef: any): void => {
const newEmployment = cloneDeep(props.resume.employmentHistory.positions)
newEmployment.splice(index, 1)
props.setResume(
{
...props.resume, employmentHistory:
{
...props.resume.employmentHistory,
positions: newEmployment
}
}
)
const refs = {} as any;
newEmployment.map(
(position: any, index: number) =>
refs[index] = position.description
)
editorsRef.current = refs;
console.log(newEmployment, editorsRef.current)
}
And here is the iteration of the editor that has the value of useReff, and the interaction and everything related to how I change the state, something Is missing but I don't know, I really don't.
//#ts-nocheck
import { Item } from '../..';
import { WorkItemValidation } from '../../../../../utils/Validation';
import { Date, Input } from '../../../Shared';
import { Editor } from '../../..';
import { Items } from '../Components';
import { Container, Liner, Linerier } from './Components'
import { useCallback, useEffect, useRef, useState } from 'react';
import { Employment as Work } from '../../../../../utils/operations/Resume';
import { debounce } from 'lodash';
const Employment: any = (props: any) => {
const [isDatePickerOpen, setIsDatePickerOpen] = useState(false);
const [loading, setLoading] = useState(true);
const editorsRef = useRef({})
const currentIndexRef = useRef('')
console.log(props, 'props', editorsRef, 'editorsRef')
useEffect(() => {
if (loading === true) {
const refs = {}
props.resume.employmentHistory.positions.map(
(position: any, index: number) =>
refs[index] = position.description
)
editorsRef.current = refs;
setLoading(false);
}
}, [])
const isFocusedRef = useRef(false);
const autoUpdateCallbackRef = useRef(null);
const callWorkDescription = useCallback(
debounce((props, currentIndex, editor) => {
Work.Description(props, currentIndex, editor);
currentIndexRef.current = ''
}, 1000),
[]
);
const handleDescription = (e: any, index: number) => {
currentIndexRef.current = index
editorsRef.current = {
...editorsRef.current,
[index]: e,
}
callWorkDescription(props, index, e)
};
useEffect(() => {
const intervalId = setInterval(() => {
if (isFocusedRef.current) autoUpdateCallbackRef.current?.();
}, 1000);
return () => clearInterval(intervalId);
}, []);
const handleFocus = () => isFocusedRef.current = true;
const handleBlur = () => isFocusedRef.current = false;
return (
<Container>
{
loading === false &&
<Items>
{
props.resume.employmentHistory.positions.map(
(position: any, index: number) => {
return (
<Item delete={() => Work.Delete(props, index, editorsRef)}
>
<Liner style={{ width: '100%' }}>
<Editor
id={`editor-${index}`}
label="Description"
value={editorsRef.current[index] && editorsRef.current[index] || ''}
placeholder="Brief description of the role..."
onChange={(e) => handleDescription(e, index)}
onFocus={handleFocus}
onBlur={handleBlur}
/>
</Liner>
</Item>
)
}
)
}
</Items>
}
</Container >
)
}
export default Employment;

search in react js : i want to serch my name and get both name and id

i am trying to do a search in react js and its working the only problem is i am not able to get one more value in to my serch result (id)
import React from "react";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import { faSearch } from "#fortawesome/free-solid-svg-icons";
import { useState, useEffect } from "react";
import axios from "axios";
const initialState = {
idaddProducts: "",
};
const Searchclients = () => {
const [showResults, setShowResults] = React.useState(true);
const [poName, pnName] = React.useState(initialState);
const [showSerch, setShowSerch] = React.useState([]);
const [inputValue, setInputValue] = React.useState("");
const [filteredSuggestions, setFilteredSuggestions] = React.useState([]);
const [selectedSuggestion, setSelectedSuggestion] = React.useState(0);
const [displaySuggestions, setDisplaySuggestions] = React.useState(false);
//const [suggestions, setSuggestions] = useState([]);
const suggestions = [];
showSerch.forEach(function (data) {
var data = data.firstname; /////// i pass the name from here i also want to pass id it will look something like this var data = data.id
suggestions.push(data);
});
const onChange = (event) => {
const value = event.target.value;
setInputValue(value);
setShowResults(false);
const filteredSuggestions = suggestions.filter((suggestion) =>
suggestion.toString().toLowerCase().includes(value.toLowerCase())
);
setFilteredSuggestions(filteredSuggestions);
setDisplaySuggestions(true);
};
const onSelectSuggestion = (index) => {
setSelectedSuggestion(index);
setInputValue(filteredSuggestions[index]);
setFilteredSuggestions([]);
setDisplaySuggestions(false);
};
const SuggestionsList = (props) => {
function finddoctor(e) {}
const {
suggestions,
inputValue,
onSelectSuggestion,
displaySuggestions,
selectedSuggestion,
} = props;
if (inputValue && displaySuggestions) {
if (suggestions.length > 0) {
return (
<ul className="suggestions-list" style={styles.ulstyle}>
{suggestions.map((suggestion, index) => {
const isSelected = selectedSuggestion === index;
const classname = `suggestion ${isSelected ? "selected" : ""}`;
return (
<li
style={styles.listyle}
key={index}
className={classname}
onClick={finddoctor(index)}
>
{suggestion} {id } // i want the id passed here
</li>
);
})}
</ul>
);
} else {
return <div>No suggestions available...</div>;
}
}
return <></>;
};
useEffect(() => {
axios
.get("my-url")
.then((res) => {
const data = res.data;
setShowSerch(data);
});
}, []);
return (
<div className="note-container" style={styles.card}>
<div style={styles.inner}>
<p style={{ textAlign: "left" }}>Search Doctors</p>
<form className="search-form" style={{}}>
{showResults ? (
<FontAwesomeIcon style={{ marginRight: "-23px" }} icon={faSearch} />
) : null}
<input
onChange={onChange}
value={inputValue}
style={styles.input}
type="Search"
/>
<SuggestionsList
// onClick={() => onSelectSuggestion()}
inputValue={inputValue}
selectedSuggestion={selectedSuggestion}
onSelectSuggestion={onSelectSuggestion}
displaySuggestions={displaySuggestions}
suggestions={filteredSuggestions}
/>
</form>
</div>
</div>
);
};
i am trying to get name and id based on searching my with name but i am able to pass only the name throgh filter
the code works and i am able to get all names based on the search but i also want the id there
I think you can do this:
Use the entire object in the suggestion, like this:
showSerch.forEach(function (data) {
suggestions.push(data);
});
Note: I believe this forEach could be unnecessary.
In the filter method you can compare the value with name or id, like this:
const filteredSuggestions = suggestions.filter((suggestion) => suggestion.name.toString().toLowerCase().includes(value.toLowerCase()) || suggestion.id.toString().toLowerCase().includes(value.toLowerCase()));
In the li tag:
{suggestion.name} {suggestion.id} // i want the id passed here
I'm assuming the suggestion have an id attribute, if not, use the correct one.

I am trying to do a grocery basket application where I want to show an alert and want it to disappear after 2 seconds

If you see below, there is a component named TimeOut() in which I am using the useEffect() to set the timer for the alert.
And then I'm calling <TimeOut/> inside the handleSubmit() function inside if(!name). I get an error where I call <TimeOut/> "expected an assignment or function call and instead saw an expression".
import React, { useState, useEffect } from 'react'
import List from './List'
import Alert from './Alert'
function App() {
const [name, setName]= useState('');
const [list, setList] = useState([]);
const [isEditing, setIsEditing] = useState(false);
const [editID, setEditID] = useState(null);
const [alert, setAlert ] = useState({show: false, msg:'', type:''});
const TimeOut =()=>{
useEffect(() => {
setInterval(() => {
// type in message here
setAlert({show:true, msg:'testing this will be displayed with name', type:''})
}, 2000);
}, []);
return <div></div>;
}
const handleSubmit = (e) => {
e.preventDefault();
if (!name) {
// console.log('testing');
//setAlert({show:true, msg:'Value cannot be empty u idiot', type:''});
<TimeOut/>
} else if (name && isEditing) {
} else {
const newItem = { id: new Date().getTime().toString(), title: name };
setList([...list, newItem]);
setName('');
}
};
const forOnChange = (e) =>{
setName(e.target.value);
}
const showAlert = (show= false, type= '', msg= '')=>{
setAlert({show:show, msg:msg, type:type})
}
const removeAllItems = ()=>{
setAlert({show: true, msg: 'List is empty now', type:''});
setList([]);
}
const removeSpecificItem = (id)=>{
const newList = list.filter((item) => item.id !== id);
setList(newList);
}
return (
<section className="section-center">
<form action="" onSubmit={handleSubmit}>
{alert.show ? <Alert alert={alert} removeAlert={showAlert}/> : null}
<h4>Grocery basket</h4>
<input type="text" placeholder="chickets etc" onChange={(e) => setName(e.target.value)}/>
<button value={name} >{isEditing ? 'Edit' : 'Submit'}</button>
<button className="clear-btn" onClick={removeAllItems}>Clear all items</button>
</form>
{list.length > 0 ? <div className="grocery-container">
<List items={list} removeSpecificItem={removeSpecificItem}/>
</div> : null}
</section>
);
}
export default App
Error
Line 31:7: Expected an assignment or function call and instead saw an expression no-unused-expressions
Line 31:8: 'Timeout' is not defined react/jsx-no-undef
The error is at
try this
const handleSubmit = (e) => {
e.preventDefault();
if (!name) {
// console.log('testing');
// <TimeOut/> remove this, you cant use react components here
setAlert({show:true, msg:'Value cannot be empty u idiot', type:''});
setTimeout(function () {
setAlert({show:false, msg:'Value cannot be empty u idiot', type:''});
}, 2000)
} else if (name && isEditing) {
} else {
const newItem = { id: new Date().getTime().toString(), title: name };
setList([...list, newItem]);
setName('');
}
};

How to write an onChange event through hooks?

I would like to register the event onChange through Hooks
const { i18n } = useTranslation();
const [locale, setLocale] = useState('en')
const handleChange = (lang) => {
setLocale(lang)
i18n.changeLanguage(lang);
}
tried using the select but ended up choosing Switch
``return (
<div className={styles.wrapper}>
<div className={styles.switchBorder}>
<Switch className={styles.switch} checkedChildren="EN" unCheckedChildren="RU"
checked={locale} onChange={(e) => handleChange(e.target.checked)}
/>
</div>
</div>
)``
const handleChange = ({currentTarget}) => {
const {checked: lang} = currentTarget;
setLocale(lang)
i18n.changeLanguage(lang);}
onChange={handleChange}
const handleChange = () => {
if (locale === 'en') {
setLocale('ru');
i18n.changeLanguage( 'ru');
} else {
setLocale('en');
i18n.changeLanguage( 'en');
}
};

Resources