hiding only the selected component - javascript

hides only the selected component. I am unable to hide only a specific component
useEffect(() => { result() }, []);
const dataComponent = state.data.map((video, index) => {
return <>
<p onClick={() => showMoreInfo(!showing)}>show</p>
{showing
? <ContainerFilmHome key={index} name={video.show_name} pictures={video.pictures}/>
: null}
</>
})

You need update showing to store index of item selected:
onClick={() => showMoreInfo(index === showing ? null : index)}
{showing === index
? <ContainerFilmHome key={index} name={video.show_name} pictures={video.pictures}/>
: null}

Related

react functional component: After first value not able to continue type the value in input element

I'm trying to update value in react functional compoenent through input element but after the first value I'm unable to type
My Code:
import React from "react";
import "./App.css";
const { useState } = React;
function App() {
const [items, setItems] = useState([
{ value: "" },
{ value: "" },
{ value: "" },
]);
const [count, setCount] = useState(0);
const Item = React.memo(({ id, value, onChange }) => {
return (
<div className="item">Item
<input
onChange={(e) => onChange(id, e.target.value)}
value={value}
/>
</div>
);
});
return (
<div className="app">
<h1>Parent</h1>
<p style={{marginTop: '20px'}}>Holds state: {count}, Does't passes to it items</p>
<p style={{marginTop: '20px'}}>{JSON.stringify(items)}</p>
<button onClick={() => setCount((prev) => prev + 1)} style={{marginTop: '20px'}}>
Update Parent
</button>
<ul className="items" style={{marginTop: '20px'}}>
{items.map((item, index) => {
return (
<Item
key={index}
id={index}
value={item.value}
onChange={(id, value) =>
setItems(
items.map((item, index) => {
return index !== id
? item
: { value: value };
})
)
}
/>
);
})}
</ul>
</div>
);
}
export default App;
You should move the Item declaration outside the App component. Having a component declaration inside another one is almost always a bad idea. Explanation below.
import React, { useState } from "react";
const Item = React.memo(({ id, value, onChange }) => {
return (
<div className="item">
Item
<input onChange={(e) => onChange(id, e.target.value)} value={value} />
</div>
);
});
function App() {
const [items, setItems] = useState([
{ value: "" },
{ value: "" },
{ value: "" }
]);
const [count, setCount] = useState(0);
return (
<div className="app">
<h1>Parent</h1>
<p style={{ marginTop: "20px" }}>
Holds state: {count}, Does't passes to it items
</p>
<p style={{ marginTop: "20px" }}>{JSON.stringify(items)}</p>
<button
onClick={() => setCount((prev) => prev + 1)}
style={{ marginTop: "20px" }}
>
Update Parent
</button>
<ul className="items" style={{ marginTop: "20px" }}>
{items.map((item, index) => {
return (
<Item
key={index}
id={index}
value={item.value}
onChange={(id, value) =>
setItems(
items.map((item, index) => {
return index !== id ? item : { value: value };
})
)
}
/>
);
})}
</ul>
</div>
);
}
export default App;
When a component definition is inside another component, React will re-declare the inner component every time the parent re-renders. This means, that any state held by the inner component will be lost.
In your case, since every time there is an entirely new component, the input was not the same input as in the previous render. This means that the input that was in focus in the previous render is not present anymore, and the new input is not focused anymore.
You should also probably change
setItems(
items.map((item, index) => {
return index !== id ? item : { value: value };
})
)
to
prev.map((item, index) => {
return index !== id ? item : { value: value };
})
)
It's a good idea to use the function notation for set state when the new state depends on the old state value.

Getting the element that was clicked in functional component in React

I'm new to React and can't get the clicked element.
"this" in functional component doesn't work
function Test(data) {
function getElement() {
}
return (
<div>
{data.map((option: any, index: any) => (
<Text
key={index}
onClick={() => getElement()}
>
{option}
</Text>
))}
</div>
)
}
there are several elements in the data that I want to switch one by one, changing the class 'active', but it is not possible to get the element that was clicked
Be sure to pass the event to your click handler:
function Test(data) {
const handleClick = e => {
const el = e.target
console.log(el)
}
return (
<div>
{data.map((option: any, index: any) => (
<Text
key={index}
onClick={handleClick}
>
{option}
</Text>
))}
</div>
)
}

why checkbox is not checked in react?

I am trying to implement Auto complete having checkbox.
https://material-ui.com/components/autocomplete/#autocomplete
but when I am implementing same component in final-form I am not able to checked my option why ?
here is my code
https://codesandbox.io/s/relaxed-breeze-hv58o
<Autocomplete
{...rest}
multiple={multiple}
disableCloseOnSelect={true}
options={
multiple
? maxReached
? []
: options.filter(option => !value.includes(option.value))
: options
}
defaultValue={
multiple
? options.filter(option => value.includes(option.value))
: options.find(option => option.value === value)
}
onChange={
multiple
? (_e, values) => {
setMaxReached(value.length >= max - 1);
onChange(values.map(option => option.value));
}
: (_e, option) => onChange(option.value)
}
getOptionLabel={option => option.label}
noOptionsText={
maxReached
? formatMessage({ id: "components.autocomplete.max" }, { max })
: formatMessage({ id: "components.autocomplete.no" })
}
renderOption={(option, { selected }) => (
<React.Fragment>
<Checkbox
icon={icon}
checkedIcon={checkedIcon}
style={{ marginRight: 8 }}
checked={selected}
/>
{option.label}
</React.Fragment>
)}
renderInput={params => (
<TextField
{...params}
{...restInput}
label={label}
placeholder={placeholder || ""}
helperText={
hasError ? formatMessage({ id: error }, { label }) : helperText
}
error={hasError}
fullWidth
/>
)}
/>
);
};
You have some issues with your code (fixed version):
You are calling onChange that makes React-Final-Form re-render, which leads for Autocomplete component to re-render, and remove the select state. To fix this, you will have to use getOptionSelected option.
getOptionSelected={(option, value) => {
return option.value === value.value;
}}
options={
options
}
onChange={(_e, values) => {
onChange(values);
}
You are filtering options based to Autocomplete component, so selected option gets filtered out.
so from this:
options={
multiple
? maxReached
? []
: options.filter(option => !value.includes(option.value))
: options
}
To
options={
options
}

Clear icon displaying on all elements in react

I'm trying to display a remove icon on a grid display that the users mouse is hovering over.
this.state = {
action: [],
}
<div>
{this.state.action.map((value, index) => {
return (
<div key={index} onMouseEnter={this.removeElementIcon} onMouseLeave={this.hideRemoveElementIcon} className={classes.gridClass}>
<Grid className={classes.marginGrid}>
<Paper className={classes.paddingPaper}>
<Typography variant={"h5"}>{value}</Typography>
<Typography component={"p"}>{value}</Typography>
</Paper>
</Grid>
{this.state.removeElementIcon ?
<IconButton className={classes.removeElement} color={"secondary"} arial-label={"remove element"} onClick={()=> this.removeElement(value)}>
<ClearIcon color={"error"} />
</IconButton>
: null}
</div>
I've tried just returning some jsx from the method itself.
removeElementIcon = () => {
return ({
this.state.removeElementIcon ?
<IconButton className={classes.removeElement} color={"secondary"}
arial-label={"remove element"} onClick={() => this.removeElement(value)}>
<ClearIcon color={"error"}/>
</IconButton> :
null
});
Instead of:
removeElementIcon = () => {
this.setState({removeElementIcon: true});
};
hideRemoveElementIcon = () => {
this.setState({removeElementIcon: false});
};
Instead of just displaying the clear icon on one element it displays on all elements.
You need to maintain item index in state,
this.state = {
action: [],
hoverIndex: '',
}
Pass the index to your removeElementIcon function,
<div
key={index}
onMouseEnter={() => this.removeElementIcon(index)}
onMouseLeave={hideRemoveElementIcon}
className={classes.gridClass}
>
...
</div>
In your function's set the hoverIndex,
removeElementIcon = (index) => {
this.setState({removeElementIcon: true, hoverIndex: index});
};
hideRemoveElementIcon = () => {
this.setState({removeElementIcon: false, hoverIndex:''});
};
And finally apply the condition,
{this.state.removeElementIcon && this.state.hoverIndex === index ?
<IconButton className={classes.removeElement} color={"secondary"} arial-label={"remove element"} onClick={() => this.removeElement(value)}>
<ClearIcon color={"error"}/>
</IconButton>
: null
}
or even short way
{this.state.removeElementIcon && this.state.hoverIndex === index &&
<IconButton className={classes.removeElement} color={"secondary"} arial-label={"remove element"} onClick={() => this.removeElement(value)}>
<ClearIcon color={"error"}/>
</IconButton>
}
Demo with simple button.

How to add class to clicked element only in reactjs?

I have dynamic menu items created from api. I'm calling class change function onClick but class is adding to all menus. I need add class to only clicked element not to whole menu list below is my code.
{menuSideBar.map(menu => (
<ListItem
className={SideMenuClass.join(" ")}
onClick={this.toggleClass.bind(this)}
button
>
<ListItemIcon className="sidebar_menu_icons">
<SendIcon />
</ListItemIcon>
<Link className="sidebar_menu_links" to={menu.url != "" ? "/" + menu.url : "#"}>
<ListItemText inset primary={menu.resourceValue} />
</Link>
</ListItem>
))}
Below is function
toggleClass = () => {
this.setState({ addClass: !this.state.addClass });
};
let SideMenuClass = ["sidebar_menu_list"];
if (this.state.addClass) {
SideMenuClass.push("selected_sidebar_menu");
}
Please help how can I add class to only clicked element?
Thank you.
You can save id's of selected items as array in state
{menuSideBar.map(menu => (
<Item
className={this.state.ids.includes(menu.id) ? 'active' : ''}
onClick={() => {
this.setState(oldState => ({
ids: oldState.ids.includes(menu.id) ? oldState.ids.filter(x => x !== menu.id) : [...oldState.ids, menu.id]
}));
}}
button
/>
))}
Example: https://codesandbox.io/s/4wv6n31q90?fontsize=14
Or if you need only last one selected:
{menuSideBar.map(menu => (
<Item
className={this.state.lastClicked === menu.id ? 'active' : ''}
onClick={() => {
this.setState({lastClicled: menu.id});
}}
button
/>
))}
Store menu item id in the state - then in render (map) check if equals to current element - adjust classes acordingly (apply class for selected only).

Categories