How to apply animation in React JS - javascript

I'm using react-animated-css library to apply animations on state change in React JS.
The code is as follows:
import ReactDOM from "react-dom";
import React, { Component } from "react";
import { Animated } from "react-animated-css";
const animationIn = "fadeInLeft";
const animationOut = "fadeOutLeft";
const animationDuration = 400; // in ms
const arr = [
{
id: 1,
name: "Test"
},
{
id: 2,
name: "Test1"
},
{
id: 3,
name: "Test3"
},
{
id: 4,
name: "Test4"
},
{
id: 5,
name: "Test5"
}
];
class Selection extends Component {
constructor(props) {
super(props);
this.state = {
selection: []
};
this.addSelection = this.addSelection.bind(this);
this.removeItem = this.removeItem.bind(this);
}
addSelection(item) {
const exists = this.state.selection.find(i => i.id === item.id);
if (exists === undefined) {
this.setState({ selection: [...this.state.selection, item] });
}
}
removeItem(item) {
this.setState({
selection: this.state.selection.filter(i => i.id !== item.id)
});
}
render() {
return (
<div
style={{
display: "flex",
flexDirection: "row",
justifyContent: "space-between"
}}
>
<div>
<h2>Choose from the list</h2>
{arr.map(item => {
return (
<div
key={item.id}
style={{ marginBottom: 5, cursor: "pointer" }}
onClick={() => this.addSelection(item)}
>
{item.name}
</div>
);
})}
</div>
<div>
<h1>Selection</h1>
{this.state.selection.length < 1 ? (
<div>Nothing selected</div>
) : (
this.state.selection.map(l => {
return (
<Animated
key={l.name}
animationIn={animationIn}
animationOut={animationOut}
animationInDuration={animationDuration}
animationOutDuration={animationDuration}
isVisible={true}
>
<div key={l.id} style={{ marginBottom: 5 }}>
{l.name}
<button
onClick={() => this.removeItem(l)}
style={{ marginLeft: 5, cursor: "pointer" }}
>
Remove
</button>
</div>
</Animated>
);
})
)}
</div>
</div>
);
}
}
ReactDOM.render(<Selection />, document.getElementById("root"));
It works fine when I click on some item on the left and add it to the state, but when I remove it it doesn't work.
Here is the example on sandbox.
Any idea how to apply the animation also on removing items from the state?

You need to play with the state of the props visible of your animation and add timeout.
addSelection(item) {
const exists = this.state.selection.find(i => i.id === item.id);
if (exists === undefined) {
this.setState({
selection: [...this.state.selection, item],
[`visibleAnimate${item.id}`]: true
});
}
}
removeItem(item) {
this.setState(
{
[`visibleAnimate${item.id}`]: false
// selection: this.state.selection.filter(i => i.id !== item.id)
},
() => {
setTimeout(() => {
this.setState({
selection: this.state.selection.filter(i => i.id !== item.id)
});
}, 300);
}
);
}
Here the sandbox demo.

From a glance, it looks like you remove the animation with the item, which is why it doesn't play.
Does it work if you wrap the animation around the whole selection list, starting below your h1?

You have to toggle the isVisible property to see the out animation. If the component is unmounted, it cannot be animated out.

Related

How to add and edit list items in a dual list in reactjs?

I am pretty new to React js and trying different ways to make a to-do list to understand it further. I have a parent component that renders two child components. I figured out how to transfer the items between the two lists. How do I add items to the 2 lists separately from the UI? I am not able to figure that out. I need two input textboxes for each list and also should be able to edit the list items. Can anybody please help me?
import React,{useState,useEffect} from 'react'
import { Completed } from './Completed'
import { Pending } from './Pending'
export const Items = () => {
const [items,setItems]=useState([
{
id: 1,
title:'Workout',
status:'Pending'
},
{
id: 2,
title:'Read Books',
status:'Pending'
},
{
id: 3,
title:'Cook Pizza',
status:'Pending'
},
{
id: 4,
title:'Pay Bills',
status:'Completed'
},
{
id: 5,
title:' Watch Big Short',
status:'Completed'
},
{
id: 6,
title:' Make nutrition Plan',
status:'Pending'
}
])
const updateStatus=(id,newStatus)=>{
let allItems=items;
allItems=allItems.map(item=>{
if(item.id===id){
console.log('in here')
item.status=newStatus;
}
return item
})
setItems(allItems)
}
return (
<div class="items">
<Pending items={items} setItems={setItems} updateStatus={updateStatus}/>
<Completed items={items} setItems={setItems} updateStatus={updateStatus}/>
</div>
)
}
import React from 'react'
export const Completed = ({items,setItems,updateStatus}) => {
return (
<div className="completed">
<h1>RIGHT</h1>
{
items && items.map(item=>{
if(item && item.status==='Completed')
return <><p className="item" key={item.id}>{item.title} <button className="mark_pending" key={item.id} onClick={()=>{updateStatus(item.id,'Pending')}}> Move Left</button></p></>
})
}
</div>
)
}
import React from 'react'
export const Pending = ({items,setItems,updateStatus}) => {
return (
<div className="pending">
<h1>LEFT</h1>
{
items && items.map(item=>{
if(item && item.status==='Pending')
return <><p className="item" key={item.id}>{item.title} <button className="mark_complete" key={item.id} onClick={()=>{updateStatus(item.id,'Completed')}}>Move Right</button></p></>
})
}
</div>
)
}
What do you mean by "separately from the UI" ?
import React, { useState } from "react";
const initialStatus = "Pending";
const initialData = [
{
id: 1,
title: "Workout",
status: "Pending",
},
{
id: 2,
title: "Read Books",
status: "Pending",
},
{
id: 3,
title: "Cook Pizza",
status: "Pending",
},
{
id: 4,
title: "Pay Bills",
status: "Completed",
},
{
id: 5,
title: " Watch Big Short",
status: "Completed",
},
{
id: 6,
title: " Make nutrition Plan",
status: "Pending",
},
];
const Box = ({ id, title, status, setItems, items }) => {
return (
<button
onClick={() => {
const newItems = [...items];
const index = items.findIndex((v) => v.id == id);
newItems[index].status =
newItems[index].status == initialStatus ? "Completed" : initialStatus;
setItems(newItems);
}}
>
{title}
</button>
);
};
export const Items = () => {
const [items, setItems] = useState(initialData);
return (
<div style={{ display: "flex" }}>
<div style={{ display: "flex", flexDirection: "column" }}>
<h1>LEFT</h1>
{items
.filter((v) => v.status === initialStatus)
.map((props) => (
<Box {...props} key={props.id} setItems={setItems} items={items} />
))}
</div>
<div style={{ display: "flex", flexDirection: "column" }}>
<h1>Right</h1>
{items
.filter((v) => v.status !== initialStatus)
.map((props) => (
<Box {...props} key={props.id} setItems={setItems} items={items} />
))}
</div>
</div>
);
};
export default Items;

Uber eats type Horizontal ScrollSpy with scroll arrows

What i am looking for is uber eats type menu style with auto horizontal scroll if the menu categories are more then the total width that is available and When the user scroll down, the menu active links keeps changing according to the current category that being viewed.
I am using material-ui at the moment and its Appbar, Tabs and TabPanel only allow a single category items to be displayed at the same time, not all, i have to click on each category to view that category items, unlike uber eats where you can just keep scrolling down and the top menu categories indicator keeps on reflecting the current position.
I searched a lot but i didn't find any solution to my problem or even remotely related one too.
Any help, suggestion or guide will be appreciated or if there is any guide of something related to this that i have missed, link to that will be awesome.
By following this Code Sandbox
https://codesandbox.io/s/material-demo-xu80m?file=/index.js
and customizing it to my needs i did came up with my required scrolling effect by using MaterialUI.
The customized component code is:
import React from "react";
import throttle from "lodash/throttle";
import { makeStyles, withStyles } from "#material-ui/core/styles";
import useStyles2 from "../styles/storeDetails";
import Tabs from "#material-ui/core/Tabs";
import Tab from "#material-ui/core/Tab";
import { Grid } from "#material-ui/core";
import MenuCard from "./MenuCard";
const tabHeight = 69;
const StyledTabs = withStyles({
root: {
textAlign: "left !important",
},
indicator: {
display: "flex",
justifyContent: "center",
backgroundColor: "transparent",
"& > div": {
maxWidth: 90,
width: "100%",
backgroundColor: "rgb(69, 190, 226)",
},
},
})((props) => <Tabs {...props} TabIndicatorProps={{ children: <div /> }} />);
const StyledTab = withStyles((theme) => ({
root: {
textTransform: "none",
height: tabHeight,
textAlign: "left !important",
marginLeft: -30,
marginRight: 10,
fontWeight: theme.typography.fontWeightRegular,
fontSize: theme.typography.pxToRem(15),
[theme.breakpoints.down("sm")]: {
fontSize: theme.typography.pxToRem(13),
marginLeft: -10,
},
"&:focus": {
opacity: 1,
},
},
}))((props) => <Tab disableRipple {...props} />);
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
},
indicator: {
padding: theme.spacing(1),
},
demo2: {
backgroundColor: "#fff",
position: "sticky",
top: 0,
left: 0,
right: 0,
width: "100%",
},
}));
const makeUnique = (hash, unique, i = 1) => {
const uniqueHash = i === 1 ? hash : `${hash}-${i}`;
if (!unique[uniqueHash]) {
unique[uniqueHash] = true;
return uniqueHash;
}
return makeUnique(hash, unique, i + 1);
};
const textToHash = (text, unique = {}) => {
return makeUnique(
encodeURI(
text
.toLowerCase()
.replace(/=>|<| \/>|<code>|<\/code>|'/g, "")
// eslint-disable-next-line no-useless-escape
.replace(/[!##\$%\^&\*\(\)=_\+\[\]{}`~;:'"\|,\.<>\/\?\s]+/g, "-")
.replace(/-+/g, "-")
.replace(/^-|-$/g, "")
),
unique
);
};
const noop = () => {};
function useThrottledOnScroll(callback, delay) {
const throttledCallback = React.useMemo(
() => (callback ? throttle(callback, delay) : noop),
[callback, delay]
);
React.useEffect(() => {
if (throttledCallback === noop) return undefined;
window.addEventListener("scroll", throttledCallback);
return () => {
window.removeEventListener("scroll", throttledCallback);
throttledCallback.cancel();
};
}, [throttledCallback]);
}
function ScrollSpyTabs(props) {
const [activeState, setActiveState] = React.useState(null);
const { tabsInScroll } = props;
let itemsServer = tabsInScroll.map((tab) => {
const hash = textToHash(tab.name);
return {
icon: tab.icon || "",
text: tab.name,
component: tab.products,
hash: hash,
node: document.getElementById(hash),
};
});
const itemsClientRef = React.useRef([]);
React.useEffect(() => {
itemsClientRef.current = itemsServer;
}, [itemsServer]);
const clickedRef = React.useRef(false);
const unsetClickedRef = React.useRef(null);
const findActiveIndex = React.useCallback(() => {
// set default if activeState is null
if (activeState === null) setActiveState(itemsServer[0].hash);
// Don't set the active index based on scroll if a link was just clicked
if (clickedRef.current) return;
let active;
for (let i = itemsClientRef.current.length - 1; i >= 0; i -= 1) {
// No hash if we're near the top of the page
if (document.documentElement.scrollTop < 0) {
active = { hash: null };
break;
}
const item = itemsClientRef.current[i];
if (
item.node &&
item.node.offsetTop <
document.documentElement.scrollTop +
document.documentElement.clientHeight / 8 +
tabHeight
) {
active = item;
break;
}
}
if (active && activeState !== active.hash) {
setActiveState(active.hash);
}
}, [activeState, itemsServer]);
// Corresponds to 10 frames at 60 Hz
useThrottledOnScroll(itemsServer.length > 0 ? findActiveIndex : null, 166);
const handleClick = (hash) => () => {
// Used to disable findActiveIndex if the page scrolls due to a click
clickedRef.current = true;
unsetClickedRef.current = setTimeout(() => {
clickedRef.current = false;
}, 1000);
if (activeState !== hash) {
setActiveState(hash);
if (window)
window.scrollTo({
top:
document.getElementById(hash).getBoundingClientRect().top +
window.pageYOffset,
behavior: "smooth",
});
}
};
React.useEffect(
() => () => {
clearTimeout(unsetClickedRef.current);
},
[]
);
const classes = useStyles();
const classes2 = useStyles2();
return (
<>
<nav className={classes2.rootCategories}>
<StyledTabs
value={activeState ? activeState : itemsServer[0].hash}
variant="scrollable"
scrollButtons="on"
>
{itemsServer.map((item2) => (
<StyledTab
key={item2.hash}
label={item2.text}
onClick={handleClick(item2.hash)}
value={item2.hash}
/>
))}
</StyledTabs>
<div className={classes.indicator} />
</nav>
<div className={classes2.root}>
{itemsServer.map((item1, ind) => (
<>
<h3 style={{ marginTop: 30 }}>{item1.text}</h3>
<Grid
container
spacing={3}
id={item1.hash}
key={ind}
className={classes2.menuRoot}
>
{item1.component.map((product, index) => (
<Grid item xs={12} sm={6} key={index}>
<MenuCard product={product} />
</Grid>
))}
</Grid>
</>
))}
</div>
</>
);
}
export default ScrollSpyTabs;
In const { tabsInScroll } = props; I am getting an array of categories objects, which themselves having an array of products inside them.
After my customization, this is the result:

Reordering items (left to right) onclick ReactJs

In the following code I reorganize a list from bottom to top or from top to bottom.
I would rather be able to reorganize it from left to right.
Do you have any idea how to do this?
App
import React, { Component } from "react";
import FruitList from "./FruitList";
const UP = -1;
const DOWN = 1;
class App extends React.Component {
state = {
// set new state for bind key items
items: [
{ id: 1, name: "orange", bgColor: "#f9cb9c" },
{ id: 2, name: "lemon", bgColor: "#fee599" },
{ id: 3, name: "strawberry", bgColor: "#e06666" }
]
};
handleMove = (id, direction) => {
const { items } = this.state;
const position = items.findIndex(i => i.id === id);
if (position < 0) {
throw new Error("Given item not found.");
} else if (
(direction === UP && position === 0) ||
(direction === DOWN && position === items.length - 1)
) {
return; // canot move outside of array
}
const item = items[position]; // save item for later
const newItems = items.filter(i => i.id !== id); // remove item from array
newItems.splice(position + direction, 0, item);
this.setState({ items: newItems });
};
render() {
return <FruitList fruitList={this.state.items} onMove={this.handleMove} />;
}
}
export default App;
My components
import React, { Component } from "react";
const UP = -1;
const DOWN = 1;
class FruitList extends React.Component {
render() {
const { fruitList, onMove } = this.props;
return (
<div>
{fruitList.map(item => (
<div key={item.id} style={{ backgroundColor: item.bgColor }}>
<div className="fruitsId">{item.id}</div>
<div className="fruitsName">{item.name}</div>
<div className="fruitsArrows">
<a onClick={() => onMove(item.id, UP)}>▲</a>
<a onClick={() => onMove(item.id, DOWN)}>▼</a>
</div>
</div>
))}
</div>
);
}
}
export default FruitList;
You can do this using css flexbox.
I applied { display: "flex" } to the root div in FruitList. (The direction is default row).
FruitList.js
class FruitList extends React.Component {
render() {
const { fruitList, onMove } = this.props;
return (
<div style={{ display: "flex" }}>
{fruitList.map(item => (
<div
key={item.id}
style={{
backgroundColor: item.bgColor,
display: "flex",
}}
>
<div className="fruitsArrows">
<a onClick={() => onMove(item.id, LEFT)}>←</a>
</div>
<div className="fruitsId">{item.id}</div>
<div className="fruitsName">{item.name}</div>
<div className="fruitsArrows">
<a onClick={() => onMove(item.id, RIGHT)}>→</a>
</div>
</div>
))}
</div>
);
}
}
Playground

How to show message when filtered list is empty in React

I am working on a project in which I am trying to show a div of content that says No results found for if the user types letters in the search input that do not match any filter in the list. I've tried using this similar solution as reference: React: How to show message when result is zero in react, but without success.
Here is a snippet of my code and one solution (of many) I have tried so far:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
searchQuery: ""
};
}
handleSearchQuery = event => {
this.setState({ searchQuery: event.target.value });
};
resetInputField = () => {
this.setState({ searchQuery: "" });
};
render() {
const { subContent, type, options, label } = this.props;
const { searchQuery } = this.state;
return (
<div
style={{
display: "grid",
alignItems: "center",
width: "100%",
margin: "0 0 24px 0",
fontSize: "14px"
}}
>
<div style={sx.rangeInputContainer}>
<input
style={sx.rangeInputLong}
type="text"
placeholder={placeholderText}
onChange={this.handleSearchQuery}
value={searchQuery}
/>
</div>
<div>
{options
.filter(
option =>
option.label
.toLowerCase()
.includes(searchQuery.toLowerCase()) || !searchQuery
)
.map((option, index) => {
return option.label.length !== 0 ? (
<div key={index} style={sx.filterOption}>
<SquareCheckbox
type="checkbox"
id={"multiSelectCheckbox-" + option.label}
/>
<label
style={{ color: "#FFF" }}
htmlFor={"multiSelectCheckbox-" + option.label}
>
{option.label}
</label>
</div>
) : (
<div
key={index}
style={{
display: "flex",
alignItems: "center",
marginTop: "16px"
}}
>
<img
style={{ width: "20px", cursor: "pointer" }}
src={resetIconSVG}
onClick={this.resetInputField}
/>
<div style={{ marginLeft: "16px" }}>
No results found for {searchQuery}
</div>
</div>
);
})}
</div>
</div>
);
}
}
Here's a snippet of options, which is in my parent component:
this.state = {
filters: [
{
label: 'Materials',
type: FILTER_TYPE.MULTI_SELECT,
expandedHandle: ()=> {
this.handleExpandedToggle('Materials'); },
options:materials,
expanded:false,
},
{
label: 'Status',
type: FILTER_TYPE.SELECT,
expandedHandle: ()=> { this.handleExpandedToggle('Status');
},
options: status,
expanded:false,
},
],
};
And the dummy .json data I am using:
export const materials = [
{ value: 'brass', label: 'brass' },
{ value: 'chrome', label: 'chrome' },
{ value: 'ceramic', label: 'ceramic' },
{ value: 'glass', label: 'glass' },
{ value: 'concrete', label: 'concrete' },
];
export const status = [
{ value: 'Show All', label: 'Show All' },
{ value: 'Enabled Only', label: 'Enabled Only' },
];
I've made an assumption about your options data, hopefully this helps (I simplified the codes)
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
searchQuery: ''
};
}
handleSearchQuery = event => {
this.setState({ searchQuery: event.target.value });
};
resetInputField = () => {
this.setState({ searchQuery: '' });
};
render() {
const { searchQuery } = this.state;
const options = [
{ label: 'react' },
{ label: 'angular' },
{ label: 'vue' }
];
const filteredOptions = options.filter(
option =>
option.label.toLowerCase().includes(searchQuery.toLowerCase()) ||
!searchQuery
);
return (
<div>
<div>
<input
type="text"
onChange={this.handleSearchQuery}
value={searchQuery}
/>
</div>
<div>
{filteredOptions.length > 0 ? (
filteredOptions.map((option, index) => {
return <div key={index}>{option.label}</div>;
})
) : (
<div>
No results found for {searchQuery}
</div>
)}
</div>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
<script crossorigin src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<div id="root"></div>
Seems like your using a ternary operator inside of a return on your filter method. I would put the filter into a variable
const filteredOptions = options.filter(option => option.label.toLowerCase().includes(searchQuery.toLowerCase()) || !searchQuery).map((option, index) => {
return option.label.length !== 0 ? <div key={index} style={sx.filterOption}>
<SquareCheckbox type='checkbox' id={'multiSelectCheckbox-' + option.label} />
<label style={{ color: '#FFF' }} htmlFor={'multiSelectCheckbox-' + option.label}> {option.label} </label>
</div> })
and in your render use the ternary to check the length of the array
render {
return (
{filteredOptions.length > 0 ? filteredOptions : <div style = {{ marginLeft: '16px' }}>No results found for { searchQuery }</div>}
)
}

Add value of checkbox to an array when it is clicked

I have this situation where I want to transfer userid to an array which is defined in State.
I want to do it when I click on the checkbox to select it, and I want to remove the userid from the array when I deselect the checkbox
import React, { Component } from "react";
import {
View,
Text,
StyleSheet,
FlatList,
AsyncStorage
} from "react-native";
import axios from 'axios';
import { Button, Container, Content, Header, Body, Left, Right, Title } from 'native-base';
import Icon from 'react-native-vector-icons/Ionicons';
import { List, ListItem, SearchBar, CheckBox } from "react-native-elements";
// const itemId = this.props.navigation.getParam('itemId', 'NO-ID');
// const otherParam = this.props.navigation.getParam('otherParam', 'some default value');
class TeacherSubjectSingle extends Component{
static navigationOptions = {
header : null
}
// static navigationOptions = {
// headerStyle: {
// backgroundColor: '#8E44AD',
// },
// headerTintColor: '#fff',
// }
state = {
class_id: null,
userid: null,
usertype: null,
student_list: [],
faq : [],
checked: [],
}
componentWillMount = async () => {
const {class_id, student_list, userid, usertype} = this.props.navigation.state.params;
await this.setState({
class_id : class_id,
student_list : student_list,
userid : userid,
usertype : usertype,
})
console.log(this.state.class_id)
var result = student_list.filter(function( obj ) {
return obj.class_section_name == class_id;
});
this.setState({
student_list: result[0]
})
}
renderSeparator = () => {
return (
<View
style={{
height: 1,
width: "100%",
backgroundColor: "#CED0CE",
}}
/>
);
};
checkItem = (item) => {
const { checked } = this.state;
console.log(item)
if (!checked.includes(item)) {
this.setState({ checked: [...checked, item] });
} else {
this.setState({ checked: checked.filter(a => a !== item) });
}
console.log(checked)
};
render(){
return (
<Container>
<Header style={{ backgroundColor: "#8E44AD" }}>
<Left>
<Button transparent onPress={()=> this.props.navigation.navigate('ClassTeacher')}>
<Icon name="ios-arrow-dropleft" size={24} color='white' />
</Button>
</Left>
<Body>
<Title style={{ color: "white" }}>{this.state.class_id}</Title>
</Body>
<Right>
{this.state.checked.length !== 0 ? <Button transparent onPress={()=> this.props.navigation.navigate('ClassTeacher')}>
<Text>Start Chat</Text>
</Button> : null}
</Right>
</Header>
<View style={{flex: 1, backgroundColor: '#fff'}}>
<List containerStyle={{ borderTopWidth: 0, borderBottomWidth: 0 }}>
<FlatList
data={this.state.student_list.students}
extraData={this.state.checked}
renderItem={({ item }) => (
<ListItem
// roundAvatar
title={<CheckBox
title={item.name}
checkedColor='#8E44AD'
onPress={() => this.checkItem(item.userid)}
checked={this.state.checked.includes(item.userid)}
/>}
// subtitle={item.email}
// avatar={{ uri: item.picture.thumbnail }}
//containerStyle={{ borderBottomWidth: 0 }}
onPress={()=>this.props.navigation.navigate('IndividualChat', {
rc_id: item.userid,
userid: this.state.userid,
usertype: this.state.usertype,
subject_name: this.state.student_list.subject_name
})}
/>
)}
keyExtractor={item => item.userid}
ItemSeparatorComponent={this.renderSeparator}
/>
</List>
</View>
</Container>
);
}
}
export default TeacherSubjectSingle;
const styles = StyleSheet.create({
container:{
flex:1,
alignItems:'center',
justifyContent:'center'
}
});
this is the code for the same, I have created a function checkItem()for the same and it is working, the only problem is, when I click on the first item, it will output the blank array, I select the second item and it will return the array with first item and so on. Please help me resolve it, thanks in advance
Its because you are printing this.state.checked value just after the setState, setState is async, it will not immediately update the state value.
You can use setState callback method to check the updated state values.
Write it like this:
checkItem = (item) => {
const { checked } = this.state;
let newArr = [];
if (!checked.includes(item)) {
newArr = [...checked, item];
} else {
newArr = checked.filter(a => a !== item);
}
this.setState({ checked: newArr }, () => console.log('updated state', newArr))
};
Check this answer for more details about setState:
Why calling setState method doesn't mutate the state immediately?
Try below code:
checkItem = (e) => {
let alreadyOn = this.state.checked; //If already there in state
if (e.target.checked) {
alreadyOn.push(e.target.name); //push the checked value
} else {
//will remove if already checked
_.remove(alreadyOn, obj => {
return obj == e.target.name;
});
}
console.log(alreadyOn)
this.setState({checked: alreadyOn});
}
Like this, with an event listener and the .push method of an array.
var checkboxes = document.querySelectorAll('input[type=checkbox]');
var myArray = [];
for (var i = 0; i < checkboxes.length; i++) {
checkboxes[i].addEventListener("click", function(e) {
myArray.push(e.target.value);
console.log(myArray);
});
};
<div>
<input type="checkbox" name="feature" value="scales" />
<label >Scales</label>
</div>
<div>
<input type="checkbox" name="feature" value="horns" />
<label >Horns</label>
</div>
<div>
<input type="checkbox" name="feature" value="claws" />
<label >Claws</label>
</div>

Categories

Resources