Curated collection of useful React snippets that you can understand in 30 seconds or less.
- Use Ctrl + F or command + F to search for a snippet.
- Contributions welcome, please read the contribution guide.
- Snippets are written in React 16.8+, using hooks.
To import a snippet into your project, you must import React
and copy-paste the component's JavaScript code like this:
import React from 'react';
function MyComponent(props) {
/* ... */
}
If there is any CSS related to your component, copy-paste it to a new file with the same name and the appropriate extension, then import it like this:
import './MyComponent.css';
To render your component, make sure there is a node with and id of "root"
present in your element (preferrably a <div>
) and that you have imported ReactDOM
, like this:
import ReactDOM from 'react-dom';
View contents
View contents
View contents
View contents
View contents
Renders a list of elements from an array of primitives.
- Use the value of the
isOrdered
prop to conditionally render a<ol>
or<ul>
list. - Use
Array.prototype.map
to render every item indata
as a<li>
element, give it akey
produced from the concatenation of the its index and value. - Omit the
isOrdered
prop to render a<ul>
list by default.
function DataList({ isOrdered, data }) {
const list = data.map((val, i) => <li key={`${i}_${val}`}>{val}</li>);
return isOrdered ? <ol>{list}</ol> : <ul>{list}</ul>;
}
Examples
const names = ['John', 'Paul', 'Mary'];
ReactDOM.render(<DataList data={names} />, document.getElementById('root'));
ReactDOM.render(<DataList data={names} isOrdered />, document.getElementById('root'));
Renders a table with rows dynamically created from an array of primitives.
- Render a
<table>
element with two columns (ID
andValue
). - Use
Array.prototype.map
to render every item indata
as a<tr>
element, consisting of its index and value, give it akey
produced from the concatenation of the two.
function DataTable({ data }) {
return (
<table>
<thead>
<tr>
<th>ID</th>
<th>Value</th>
</tr>
</thead>
<tbody>
{data.map((val, i) => (
<tr key={`${i}_${val}`}>
<td>{i}</td>
<td>{val}</td>
</tr>
))}
</tbody>
</table>
);
}
Examples
const people = ['John', 'Jesse'];
ReactDOM.render(<DataTable data={people} />, document.getElementById('root'));
Renders a table with rows dynamically created from an array of objects and a list of property names.
- Use
Object.keys()
,Array.prototype.filter()
,Array.prototype.includes()
andArray.prototype.reduce()
to produce afilteredData
array, containing all objects with the keys specified inpropertyNames
. - Render a
<table>
element with a set of columns equal to the amount of values inpropertyNames
. - Use
Array.prototype.map
to render each value in thepropertyNames
array as a<th>
element. - Use
Array.prototype.map
to render each object in thefilteredData
array as a<tr>
element, containing a<td>
for each key in the object.
function MappedTable({ data, propertyNames }) {
let filteredData = data.map(v =>
Object.keys(v)
.filter(k => propertyNames.includes(k))
.reduce((acc, key) => ((acc[key] = v[key]), acc), {})
);
return (
<table>
<thead>
<tr>
{propertyNames.map(val => (
<th key={`h_${val}`}>{val}</th>
))}
</tr>
</thead>
<tbody>
{filteredData.map((val, i) => (
<tr key={`i_${i}`}>
{propertyNames.map(p => (
<td key={`i_${i}_${p}`}>{val[p]}</td>
))}
</tr>
))}
</tbody>
</table>
);
}
This component does not work with nested objects and will break if there are nested objects inside any of the properties specified in propertyNames
.,<!-tags: array,object -->,<!-expertise: 1 -->
Examples
const people = [
{ name: 'John', surname: 'Smith', age: 42 },
{ name: 'Adam', surname: 'Smith', gender: 'male' }
];
const propertyNames = ['name', 'surname', 'age'];
ReactDOM.render(
<MappedTable data={people} propertyNames={propertyNames} />,
document.getElementById('root')
);
Renders an <input>
element that uses a callback function to pass its value to the parent component.
- Use object destructuring to set defaults for certain attributes of the
<input>
element. - Render an
<input>
element with the appropriate attributes and use thecallback
function in theonChange
event to pass the value of the input to the parent.
function Input({ callback, type = 'text', disabled = false, readOnly = false, placeholder = '' }) {
return (
<input
type={type}
disabled={disabled}
readOnly={readOnly}
placeholder={placeholder}
onChange={({ target: { value } }) => callback(value)}
/>
);
}
Examples
ReactDOM.render(
<Input type="text" placeholder="Insert some text here..." callback={val => console.log(val)} />,
document.getElementById('root')
);
Renders a textarea component with a character limit.
- Use the
React.useState()
hook to create thecontent
state variable and set its value tovalue
. Create a methodsetFormattedContent
, which trims the content of the input if it's longer thanlimit
. - Use the
React.useEffect()
hook to call thesetFormattedContent
method on the value of thecontent
state variable. - Use a
<div>
to wrap both the<textarea>
and the<p>
element that displays the character count and bind theonChange
event of the<textarea>
to callsetFormattedContent
with the value ofevent.target.value
.
function LimitedTextarea({ rows, cols, value, limit }) {
const [content, setContent] = React.useState(value);
const setFormattedContent = text => {
text.length > limit ? setContent(text.slice(0, limit)) : setContent(text);
};
React.useEffect(() => {
setFormattedContent(content);
}, []);
return (
<div>
<textarea
rows={rows}
cols={cols}
onChange={event => setFormattedContent(event.target.value)}
value={content}
/>
<p>
{content.length}/{limit}
</p>
</div>
);
}
Examples
ReactDOM.render(<LimitedTextarea limit={32} value="Hello!" />, document.getElementById('root'));
Renders a textarea component with a word limit.
- Use the
React.useState()
hook to create thecontent
andwordCount
state variables and set their values tovalue
and0
respectively. - Create a method
setFormattedContent
, which usesString.prototype.split(' ')
to turn the input into an array of words and check if the result of applyingArray.prototype.filter(Boolean)
has alength
longer thanlimit
. - If the afforementioned
length
exceeds thelimit
, trim the input, otherwise return the raw input, updatingcontent
andwordCount
accordingly in both cases. - Use the
React.useEffect()
hook to call thesetFormattedContent
method on the value of thecontent
state variable. - Use a
<div>
to wrap both the<textarea>
and the<p>
element that displays the character count and bind theonChange
event of the<textarea>
to callsetFormattedContent
with the value ofevent.target.value
.
function LimitedWordTextarea({ rows, cols, value, limit }) {
const [content, setContent] = React.useState(value);
const [wordCount, setWordCount] = React.useState(0);
const setFormattedContent = text => {
let words = text.split(' ');
if (words.filter(Boolean).length > limit) {
setContent(
text
.split(' ')
.slice(0, limit)
.join(' ')
);
setWordCount(limit);
} else {
setContent(text);
setWordCount(words.filter(Boolean).length);
}
};
React.useEffect(() => {
setFormattedContent(content);
}, []);
return (
<div>
<textarea
rows={rows}
cols={cols}
onChange={event => setFormattedContent(event.target.value)}
value={content}
/>
<p>
{wordCount}/{limit}
</p>
</div>
);
}
Examples
ReactDOM.render(
<LimitedWordTextArea limit={5} value="Hello there!" />,
document.getElementById('root')
);
Renders a checkbox list that uses a callback function to pass its selected value/values to the parent component.
- Use
React.setState()
to create adata
state variable and set its initial value equal to theoptions
prop. - Create a function
toggle
that is used to toggle thechecked
to update thedata
state variable and call theonChange
callback passed via the component's props. - Render a
<ul>
element and useArray.prototype.map()
to map thedata
state variable to individual<li>
elements with<input>
elements as their children. - Each
<input>
element has thetype='checkbox'
attribute and is marked asreadOnly
, as its click events are handled by the parent<li>
element'sonClick
handler.
const style = {
listContainer: {
listStyle: 'none',
paddingLeft: 0
},
itemStyle: {
cursor: 'pointer',
padding: 5
}
};
function MultiselectCheckbox({ options, onChange }) {
const [data, setData] = React.useState(options);
const toggle = item => {
data.map((_, key) => {
if (data[key].label === item.label) data[key].checked = !item.checked;
});
setData([...data]);
onChange(data);
};
return (
<ul style={style.listContainer}>
{data.map(item => {
return (
<li key={item.label} style={style.itemStyle} onClick={() => toggle(item)}>
<input readOnly type="checkbox" checked={item.checked || false} />
{item.label}
</li>
);
})}
</ul>
);
}
Examples
const options = [{ label: 'Item One' }, { label: 'Item Two' }];
ReactDOM.render(
<MultiselectCheckbox
options={options}
onChange={data => {
console.log(data);
}}
/>,
document.getElementById('root')
);
Renders a password input field with a reveal button.
- Use the
React.useState()
hook to create theshown
state variable and set its value tofalse
. - Use a
<div>
to wrap both the<input>
and the<button>
element that toggles the type of the input field between"text"
and"password"
.
function PasswordRevealer({ value }) {
const [shown, setShown] = React.useState(false);
return (
<div>
<input type={shown ? 'text' : 'password'} value={value} onChange={() => {}} />
<button onClick={() => setShown(!shown)}>Show/Hide</button>
</div>
);
}
Examples
ReactDOM.render(<PasswordRevealer />, document.getElementById('root'));
Renders a <select>
element that uses a callback function to pass its value to the parent component.
- Use object destructuring to set defaults for certain attributes of the
<select>
element. - Render a
<select>
element with the appropriate attributes and use thecallback
function in theonChange
event to pass the value of the textarea to the parent. - Use destructuring on the
values
array to pass an array ofvalue
andtext
elements and theselected
attribute to define the initialvalue
of the<select>
element.
function Select({ values, callback, disabled = false, readonly = false, selected }) {
return (
<select
disabled={disabled}
readOnly={readonly}
onChange={({ target: { value } }) => callback(value)}
>
{values.map(([value, text]) => (
<option selected={selected === value} value={value}>
{text}
</option>
))}
</select>
);
}
Examples
let choices = [
['grapefruit', 'Grapefruit'],
['lime', 'Lime'],
['coconut', 'Coconut'],
['mango', 'Mango']
];
ReactDOM.render(
<Select values={choices} selected="lime" callback={val => console.log(val)} />,
document.getElementById('root')
);
Renders a slider element that uses a callback function to pass its value to the parent component.
- Use object destructuring to set defaults for certain attributes of the
<input>
element. - Render an
<input>
element of type"range"
and the appropriate attributes, use thecallback
function in theonChange
event to pass the value of the input to the parent.
function Slider({ callback, disabled = false, readOnly = false }) {
return (
<input
type="range"
disabled={disabled}
readOnly={readOnly}
onChange={({ target: { value } }) => callback(value)}
/>
);
}
Examples
ReactDOM.render(<Slider callback={val => console.log(val)} />, document.getElementById('root'));
Renders a <textarea>
element that uses a callback function to pass its value to the parent component.
- Use object destructuring to set defaults for certain attributes of the
<textarea>
element. - Render a
<textarea>
element with the appropriate attributes and use thecallback
function in theonChange
event to pass the value of the textarea to the parent.
function TextArea({
callback,
cols = 20,
rows = 2,
disabled = false,
readOnly = false,
placeholder = ''
}) {
return (
<textarea
cols={cols}
rows={rows}
disabled={disabled}
readOnly={readOnly}
placeholder={placeholder}
onChange={({ target: { value } }) => callback(value)}
/>
);
}
Examples
ReactDOM.render(
<TextArea placeholder="Insert some text here..." callback={val => console.log(val)} />,
document.getElementById('root')
);
Renders a tree view of a JSON object or array with collapsible content.
- Use object destructuring to set defaults for certain props.
- Use the value of the
toggled
prop to determine the initial state of the content (collapsed/expanded). - Use the
React.setState()
hook to create theisToggled
state variable and give it the value of thetoggled
prop initially. - Return a
<div>
to wrap the contents of the component and the<span>
element, used to alter the component'sisToggled
state. - Determine the appearance of the component, based on
isParentToggled
,isToggled
,name
andArray.isArray()
ondata
. - For each child in
data
, determine if it is an object or array and recursively render a sub-tree. - Otherwise, render a
<p>
element with the appropriate style.
.tree-element {
margin: 0;
position: relative;
}
div.tree-element:before {
content: '';
position: absolute;
top: 24px;
left: 1px;
height: calc(100% - 48px);
border-left: 1px solid gray;
}
.toggler {
position: absolute;
top: 10px;
left: 0px;
width: 0;
height: 0;
border-top: 4px solid transparent;
border-bottom: 4px solid transparent;
border-left: 5px solid gray;
cursor: pointer;
}
.toggler.closed {
transform: rotate(90deg);
}
.collapsed {
display: none;
}
function TreeView({
data,
toggled = true,
name = null,
isLast = true,
isChildElement = false,
isParentToggled = true
}) {
const [isToggled, setIsToggled] = React.useState(toggled);
return (
<div
style={{ marginLeft: isChildElement ? 16 : 4 + 'px' }}
className={isParentToggled ? 'tree-element' : 'tree-element collapsed'}
>
<span
className={isToggled ? 'toggler' : 'toggler closed'}
onClick={() => setIsToggled(!isToggled)}
/>
{name ? <strong> {name}: </strong> : <span> </span>}
{Array.isArray(data) ? '[' : '{'}
{!isToggled && '...'}
{Object.keys(data).map((v, i, a) =>
typeof data[v] == 'object' ? (
<TreeView
data={data[v]}
isLast={i === a.length - 1}
name={Array.isArray(data) ? null : v}
isChildElement
isParentToggled={isParentToggled && isToggled}
/>
) : (
<p
style={{ marginLeft: 16 + 'px' }}
className={isToggled ? 'tree-element' : 'tree-element collapsed'}
>
{Array.isArray(data) ? '' : <strong>{v}: </strong>}
{data[v]}
{i === a.length - 1 ? '' : ','}
</p>
)
)}
{Array.isArray(data) ? ']' : '}'}
{!isLast ? ',' : ''}
</div>
);
}
Examples
let data = {
lorem: {
ipsum: 'dolor sit',
amet: {
consectetur: 'adipiscing',
elit: [
'duis',
'vitae',
{
semper: 'orci'
},
{
est: 'sed ornare'
},
'etiam',
['laoreet', 'tincidunt'],
['vestibulum', 'ante']
]
},
ipsum: 'primis'
}
};
ReactDOM.render(<TreeView data={data} name="data" />, document.getElementById('root'));
Renders a string as plaintext, with URLs converted to appropriate <a>
elements.
- Use
String.prototype.split()
andString.prototype.match()
with a regular expression to find URLs in a string. - Return a
<React.Fragment>
with matched URLs rendered as<a>
elements, dealing with missing protocol prefixes if necessary, and the rest of the string rendered as plaintext.
function AutoLink({ text }) {
const delimiter = /((?:https?:\/\/)?(?:(?:[a-z0-9]?(?:[a-z0-9\-]{1,61}[a-z0-9])?\.[^\.|\s])+[a-z\.]*[a-z]+|(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3})(?::\d{1,5})*[a-z0-9.,_\/~#&=;%+?\-\\(\\)]*)/gi;
return (
<React.Fragment>
{text.split(delimiter).map(word => {
let match = word.match(delimiter);
if (match) {
let url = match[0];
return <a href={url.startsWith('http') ? url : `http://${url}`}>{url}</a>;
}
return word;
})}
</React.Fragment>
);
}
Examples
ReactDOM.render(
<AutoLink text="foo bar baz http://example.org bar" />,
document.getElementById('root')
);
Renders an accordion menu with multiple collapsible content components.
- Define an
AccordionItem
component, pass it to theAccordion
and remove unnecessary nodes expect forAccordionItem
by identifying the function's name inprops.children
. - Each
AccordionItem
component renders a<button>
that is used to update theAccordion
via theprops.handleClick
callback and the content of the component, passed down viaprops.children
, while its appearance is determined byprops.isCollapsed
and based onstyle
. - In the
Accordion
component, use theReact.useState()
hook to initialize the value of thebindIndex
state variable toprops.defaultIndex
. - Use
Array.prototype.map
on the collected nodes to render the individual collapsiple elements. - Define
changeItem
, which will be executed when clicking anAccordionItem
's<button>
.changeItem
executes the passed callback,onItemClick
and updatesbindIndex
based on the clicked element.
function AccordionItem(props) {
const style = {
collapsed: {
display: 'none'
},
expanded: {
display: 'block'
},
buttonStyle: {
display: 'block',
width: '100%'
}
};
return (
<div>
<button style={style.buttonStyle} onClick={() => props.handleClick()}>
{props.label}
</button>
<div
className="collapse-content"
style={props.isCollapsed ? style.collapsed : style.expanded}
aria-expanded={props.isCollapsed}
>
{props.children}
</div>
</div>
);
}
function Accordion(props) {
const [bindIndex, setBindIndex] = React.useState(props.defaultIndex);
const changeItem = itemIndex => {
if (typeof props.onItemClick === 'function') props.onItemClick(itemIndex);
if (itemIndex !== bindIndex) setBindIndex(itemIndex);
};
const items = props.children.filter(item => item.type.name === 'AccordionItem');
return (
<div className="wrapper">
{items.map(({ props }) => (
<AccordionItem
isCollapsed={bindIndex === props.index}
label={props.label}
handleClick={() => changeItem(props.index)}
children={props.children}
/>
))}
</div>
);
}
Examples
ReactDOM.render(
<Accordion defaultIndex="1" onItemClick={console.log}>
<AccordionItem label="A" index="1">
Lorem ipsum
</AccordionItem>
<AccordionItem label="B" index="2">
Dolor sit amet
</AccordionItem>
</Accordion>,
document.getElementById('root')
);
Renders a carousel component.
- Use the
React.setState()
hook to create theactive
state variable and give it a value of0
(index of the first item). - Use an object,
style
, to hold the styles for the individual components. - Use the
React.setEffect()
hook to update the value ofactive
to the index of the next item, usingsetTimeout
. - Destructure
props
, compute if visibility style should be set tovisible
or not for each carousel item while mapping over and applying the combined style to the carousel item component accordingly. - Render the carousel items using
React.cloneElement()
and pass down restprops
along with the computed styles.
function Carousel(props) {
const [active, setActive] = React.useState(0);
let scrollInterval = null;
const style = {
carousel: {
position: 'relative'
},
carouselItem: {
position: 'absolute',
visibility: 'hidden'
},
visible: {
visibility: 'visible'
}
};
React.useEffect(() => {
scrollInterval = setTimeout(() => {
const { carouselItems } = props;
setActive((active + 1) % carouselItems.length);
}, 2000);
});
const { carouselItems, ...rest } = props;
return (
<div style={style.carousel}>
{carouselItems.map((item, index) => {
const activeStyle = active === index ? style.visible : {};
return React.cloneElement(item, {
...rest,
style: {
...style.carouselItem,
...activeStyle
}
});
})}
</div>
);
}
Examples
ReactDOM.render(
<Carousel
carouselItems={[
<div>carousel item 1</div>,
<div>carousel item 2</div>,
<div>carousel item 3</div>
]}
/>,
document.getElementById('root')
);
Renders a component with collapsible content.
- Use the
React.setState()
hook to create theisCollapsed
state variable with an initial value ofprops.collapsed
. - Use an object,
style
, to hold the styles for individual components and their states. - Use a
<div>
to wrap both the<button>
that alters the component'sisCollapsed
state and the content of the component, passed down viaprops.children
. - Determine the appearance of the content, based on
isCollapsed
and apply the appropriate CSS rules from thestyle
object. - Finally, update the value of the
aria-expanded
attribute based onisCollapsed
to make the component accessible.
function Collapse(props) {
const [isCollapsed, setIsCollapsed] = React.useState(props.collapsed);
const style = {
collapsed: {
display: 'none'
},
expanded: {
display: 'block'
},
buttonStyle: {
display: 'block',
width: '100%'
}
};
return (
<div>
<button style={style.buttonStyle} onClick={() => setIsCollapsed(!isCollapsed)}>
{isCollapsed ? 'Show' : 'Hide'} content
</button>
<div
className="collapse-content"
style={isCollapsed ? style.collapsed : style.expanded}
aria-expanded={isCollapsed}
>
{props.children}
</div>
</div>
);
}
Examples
ReactDOM.render(
<Collapse>
<h1>This is a collapse</h1>
<p>Hello world!</p>
</Collapse>,
document.getElementById('root')
);
Renders a countdown timer that prints a message when it reaches zero.
- Use object destructuring to set defaults for the
hours
,minutes
andseconds
props. - Use the
React.useState()
hook to create thetime
,paused
andover
state variables and set their values to the values of the passed props,false
andfalse
respectively. - Create a method
tick
, that updates the value oftime
based on the current value (i.e. decreasing the time by one second). - If
paused
orover
istrue
,tick
will return immediately. - Create a method
reset
, that resets all state variables to their initial states. - Use the the
React.useEffect()
hook to call thetick
method every second via the use ofsetInterval()
and useclearInterval()
to cleanup when the component is unmounted. - Use a
<div>
to wrap a<p>
element with the textual representation of the componentstime
state variable, as well as two<button>
elements that will pause/unpause and restart the timer respectively. - If
over
istrue
, the timer will display a message instead of the value oftime
.
function CountDown({ hours = 0, minutes = 0, seconds = 0 }) {
const [paused, setPaused] = React.useState(false);
const [over, setOver] = React.useState(false);
const [time, setTime] = React.useState({
hours: parseInt(hours),
minutes: parseInt(minutes),
seconds: parseInt(seconds)
});
const tick = () => {
if (paused || over) return;
if (time.hours == 0 && time.minutes == 0 && time.seconds == 0) setOver(true);
else if (time.minutes == 0 && time.seconds == 0)
setTime({
hours: time.hours - 1,
minutes: 59,
seconds: 59
});
else if (time.seconds == 0)
setTime({
hours: time.hours,
minutes: time.minutes - 1,
seconds: 59
});
else
setTime({
hours: time.hours,
minutes: time.minutes,
seconds: time.seconds - 1
});
};
const reset = () => {
setTime({
hours: parseInt(hours),
minutes: parseInt(minutes),
seconds: parseInt(seconds)
});
setPaused(false);
setOver(false);
};
React.useEffect(() => {
let timerID = setInterval(() => tick(), 1000);
return () => clearInterval(timerID);
});
return (
<div>
<p>{`${time.hours.toString().padStart(2, '0')}:${time.minutes
.toString()
.padStart(2, '0')}:${time.seconds.toString().padStart(2, '0')}`}</p>
<div>{over ? "Time's up!" : ''}</div>
<button onClick={() => setPaused(!paused)}>{paused ? 'Resume' : 'Pause'}</button>
<button onClick={() => reset()}>Restart</button>
</div>
);
}
Examples
ReactDOM.render(<CountDown hours="1" minutes="45" />, document.getElementById('root'));
Renders a file drag and drop component for a single file.
- Create a ref called
dropRef
for this component. - Use the
React.useState()
hook to create thedrag
andfilename
variables, initialized tofalse
and''
respectively. The variablesdragCounter
anddrag
are used to determine if a file is being dragged, whilefilename
is used to store the dropped file's name. - Create the
handleDrag
,handleDragIn
,handleDragOut
andhandleDrop
methods to handle drag and drop functionality, bind them to the component's context. - Each of the methods will handle a specific event, the listeners for which are created and removed in the
React.useEffect()
hook and its attachedcleanup()
method. handleDrag
prevents the browser from opening the dragged file,handleDragIn
andhandleDragOut
handle the dragged file entering and exiting the component, whilehandleDrop
handles the file being dropped and passes it toprops.handleDrop
.- Return an appropriately styled
<div>
and usedrag
andfilename
to determine its contents and style. - Finally, bind the
ref
of the created<div>
todropRef
.
.filedrop {
min-height: 120px;
border: 3px solid #d3d3d3;
text-align: center;
font-size: 24px;
padding: 32px;
border-radius: 4px;
}
.filedrop.drag {
border: 3px dashed #1e90ff;
}
.filedrop.ready {
border: 3px solid #32cd32;
}
function FileDrop(props) {
const [drag, setDrag] = React.useState(false);
const [filename, setFilename] = React.useState('');
let dropRef = React.createRef();
let dragCounter = 0;
const handleDrag = e => {
e.preventDefault();
e.stopPropagation();
};
const handleDragIn = e => {
e.preventDefault();
e.stopPropagation();
dragCounter++;
if (e.dataTransfer.items && e.dataTransfer.items.length > 0) setDrag(true);
};
const handleDragOut = e => {
e.preventDefault();
e.stopPropagation();
dragCounter--;
if (dragCounter === 0) setDrag(false);
};
const handleDrop = e => {
e.preventDefault();
e.stopPropagation();
setDrag(false);
if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
props.handleDrop(e.dataTransfer.files[0]);
setFilename(e.dataTransfer.files[0].name);
e.dataTransfer.clearData();
dragCounter = 0;
}
};
React.useEffect(() => {
let div = dropRef.current;
div.addEventListener('dragenter', handleDragIn);
div.addEventListener('dragleave', handleDragOut);
div.addEventListener('dragover', handleDrag);
div.addEventListener('drop', handleDrop);
return function cleanup() {
div.removeEventListener('dragenter', handleDragIn);
div.removeEventListener('dragleave', handleDragOut);
div.removeEventListener('dragover', handleDrag);
div.removeEventListener('drop', handleDrop);
};
});
return (
<div
ref={dropRef}
className={drag ? 'filedrop drag' : filename ? 'filedrop ready' : 'filedrop'}
>
{filename && !drag ? <div>{filename}</div> : <div>Drop files here!</div>}
</div>
);
}
Examples
ReactDOM.render(<FileDrop handleDrop={console.log} />, document.getElementById('root'));
Renders a link formatted to send an email.
- Destructure the component's props, use
email
,subject
andbody
to create a<a>
element with an appropriatehref
attribute. - Render the link with
props.children
as its content.
function Mailto({ email, subject, body, ...props }) {
return (
<a href={`mailto:${email}?subject=${subject || ''}&body=${body || ''}`}>{props.children}</a>
);
}
Examples
ReactDOM.render(
<Mailto email="[email protected]" subject="Hello" body="Hello world!">
Mail me!
</Mailto>,
document.getElementById('root')
);
Renders a Modal component, controllable through events.
To use the component, import Modal
only once and then display it by passing a boolean value to the isVisible
attribute.
- Use object destructuring to set defaults for certain attributes of the modal component.
- Define
keydownHandler
, a method which handles all keyboard events, which can be used according to your needs to dispatch actions (e.g. close the modal when Esc is pressed). - Use
React.useEffect()
hook to add or remove thekeydown
event listener, which callskeydownHandler
. - Use the
isVisible
prop to determine if the modal should be shown or not. - Use CSS to style and position the modal component.
.modal {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right:0;
width: 100%;
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
background-color: rgba(0, 0, 0, 0.25);
animation-name: appear;
animation-duration: 300ms;
}
.modal-dialog{
width: 100%;
max-width: 550px;
background: white;
position: relative;
margin: 0 20px;
max-height: calc(100vh - 40px);
text-align: left;
display: flex;
flex-direction: column;
overflow:hidden;
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19);
-webkit-animation-name: animatetop;
-webkit-animation-duration: 0.4s;
animation-name: slide-in;
animation-duration: 0.5s;
}
.modal-header,.modal-footer{
display: flex;
align-items: center;
padding: 1rem;
}
.modal-header{
border-bottom: 1px solid #dbdbdb;
justify-content: space-between;
}
.modal-footer{
border-top: 1px solid #dbdbdb;
justify-content: flex-end;
}
.modal-close{
cursor: pointer;
padding: 1rem;
margin: -1rem -1rem -1rem auto;
}
.modal-body{
overflow: auto;
}
.modal-content{
padding: 1rem;
}
@keyframes appear {
from {opacity: 0;}
to {opacity: 1;}
}
@keyframes slide-in {
from {transform: translateY(-150px);}
to { transform: translateY(0);}
}
function Modal({ isVisible = false, title, content, footer, onClose }){
React.useEffect(() => {
document.addEventListener('keydown', keydownHandler);
return () => document.removeEventListener('keydown', keydownHandler);
});
function keydownHandler({ key }) {
switch (key) {
case 'Escape': onClose(); break;
default:
}
}
return !isVisible ? null : (
<div className="modal" onClick={onClose}>
<div className="modal-dialog" onClick={e => e.stopPropagation()}>
<div className="modal-header">
<h3 className="modal-title">{title}</h3>
<span className="modal-close" onClick={onClose}>×</span>
</div>
<div className="modal-body">
<div className="modal-content">{ content }</div>
</div>
{footer && <div className="modal-footer">{footer}</div>}
</div>
</div>
)
}
Examples
//Add the component to the render function
function App() {
const [ isModal, setModal] = React.useState(false);
return (
<React.Fragment>
<button onClick={()=> setModal(true)}>Click Here</button>
<Modal
isVisible={ isModal }
title= "Modal Title"
content = {<p>Add your content here</p>}
footer = {<button>Cancel</button>}
onClose ={()=> setModal(false)}
/>
</React.Fragment>
)
}
ReactDOM.render( <App/>, document.getElementById('root'));
Renders a star rating component.
- Define a component, called
Star
that will render each individual star with the appropriate appearance, based on the parent component's state. - In the
StarRating
component, use theReact.useState()
hook to define therating
andselection
state variables with the initial values ofprops.rating
(or0
if invalid or not supplied) and0
. - Create a method,
hoverOver
, that updatesselected
andrating
according to the providedevent
. - Create a
<div>
to wrap the<Star>
components, which are created usingArray.prototype.map
on an array of 5 elements, created usingArray.from
, and handle theonMouseLeave
event to setselection
to0
, theonClick
event to set therating
and theonMouseOver
event to setselection
to thestar-id
attribute of theevent.target
respectively. - Finally, pass the appropriate values to each
<Star>
component (starId
andmarked
).
function Star({ marked, starId }) {
return (
<span star-id={starId} style={{ color: '#ff9933' }} role="button">
{marked ? '\u2605' : '\u2606'}
</span>
);
}
function StarRating(props) {
const [rating, setRating] = React.useState(typeof props.rating == 'number' ? props.rating : 0);
const [selection, setSelection] = React.useState(0);
const hoverOver = event => {
let val = 0;
if (event && event.target && event.target.getAttribute('star-id'))
val = event.target.getAttribute('star-id');
setSelection(val);
};
return (
<div
onMouseOut={() => hoverOver(null)}
onClick={(event) => setRating(event.target.getAttribute('star-id') || this.state.rating)}
onMouseOver={hoverOver}
>
{Array.from({ length: 5 }, (v, i) => (
<Star
starId={i + 1}
key={`star_${i + 1} `}
marked={selection ? selection >= i + 1 : rating >= i + 1}
/>
))}
</div>
);
}
Examples
ReactDOM.render(<StarRating />, document.getElementById('root'));
ReactDOM.render(<StarRating rating={2} />, document.getElementById('root'));
Renders a tabbed menu and view component.
- Define a
TabItem
component, pass it to theTab
and remove unnecessary nodes expect forTabItem
by identifying the function's name inprops.children
. - Use the
React.useState()
hook to initialize the value of thebindIndex
state variable toprops.defaultIndex
. - Use
Array.prototype.map
on the collected nodes to render thetab-menu
andtab-view
. - Define
changeTab
, which will be executed when clicking a<button>
from thetab-menu
. changeTab
executes the passed callback,onTabClick
and updatesbindIndex
, which in turn causes a re-render, evaluating thestyle
andclassName
of thetab-view
items andtab-menu
buttons according to theirindex
.
.tab-menu > button {
cursor: pointer;
padding: 8px 16px;
border: 0;
border-bottom: 2px solid transparent;
background: none;
}
.tab-menu > button.focus {
border-bottom: 2px solid #007bef;
}
.tab-menu > button:hover {
border-bottom: 2px solid #007bef;
}
function TabItem(props) {
return <div {...props} />;
}
function Tabs(props) {
const [bindIndex, setBindIndex] = React.useState(props.defaultIndex);
const changeTab = newIndex => {
if (typeof props.onTabClick === 'function') props.onTabClick(newIndex);
setBindIndex(newIndex);
};
const items = props.children.filter(item => item.type.name === 'TabItem');
return (
<div className="wrapper">
<div className="tab-menu">
{items.map(({ props: { index, label } }) => (
<button onClick={() => changeTab(index)} className={bindIndex === index ? 'focus' : ''}>
{label}
</button>
))}
</div>
<div className="tab-view">
{items.map(({ props }) => (
<div
{...props}
className="tab-view_item"
key={props.index}
style={{ display: bindIndex === props.index ? 'block' : 'none' }}
/>
))}
</div>
</div>
);
}
Examples
ReactDOM.render(
<Tabs defaultIndex="1" onTabClick={console.log}>
<TabItem label="A" index="1">
Lorem ipsum
</TabItem>
<TabItem label="B" index="2">
Dolor sit amet
</TabItem>
</Tabs>,
document.getElementById('root')
);
Renders a ticker component.
- Use the
React.useState()
hook to initialize theticker
state variable to0
. - Define two methods,
tick
andreset
, that will periodically incrementtimer
based oninterval
and resetinterval
respectively. - Return a
<div>
with two<button>
elements, each of which callstick
andreset
respectively.
function Ticker(props) {
const [ticker, setTicker] = React.useState(0);
let interval = null;
const tick = () => {
reset();
interval = setInterval(() => {
if (ticker < props.times) setTicker(ticker + 1);
else clearInterval(interval);
}, props.interval);
};
const reset = () => {
setTicker(0);
clearInterval(interval);
};
return (
<div>
<span style={{ fontSize: 100 }}>{this.state.ticker}</span>
<button onClick={this.tick}>Tick!</button>
<button onClick={this.reset}>Reset</button>
</div>
);
}
Examples
ReactDOM.render(<Ticker times={5} interval={1000} />, document.getElementById('root'));
Renders a toggle component.
- Use the
React.useState()
to initialize theisToggleOn
state variable tofalse
. - Use an object,
style
, to hold the styles for individual components and their states. - Return a
<button>
that alters the component'sisToggledOn
when itsonClick
event is fired and determine the appearance of the content based onisToggleOn
, applying the appropriate CSS rules from thestyle
object.
function Toggle(props) {
const [isToggleOn, setIsToggleOn] = React.useState(false);
style = {
on: {
backgroundColor: 'green'
},
off: {
backgroundColor: 'grey'
}
};
return (
<button onClick={() => setIsToggleOn(!isToggleOn)} style={isToggleOn ? style.on : style.off}>
{isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
Examples
ReactDOM.render(<Toggle />, document.getElementById('root'));
Renders a tooltip component.
- Use the
React.useState()
hook to create theshow
variable and initialize it tofalse
. - Return a
<div>
element that contains the<div>
that will be the tooltip and thechildren
passed to the component. - Handle the
onMouseEnter
andonMouseLeave
methods, by altering the value of theshow
variable.
.tooltip {
position: relative;
background: rgba(0, 0, 0, 0.7);
color: white;
visibility: hidden;
padding: 5px;
border-radius: 5px;
}
.tooltip-arrow {
position: absolute;
top: 100%;
left: 50%;
border-width: 5px;
border-style: solid;
border-color: rgba(0, 0, 0, 0.7) transparent transparent;
}
function Tooltip({ children, text, ...rest }) {
const [show, setShow] = React.useState(false);
return (
<div>
<div className="tooltip" style={show ? { visibility: 'visible' } : {}}>
{text}
<span className="tooltip-arrow" />
</div>
<div {...rest} onMouseEnter={() => setShow(true)} onMouseLeave={() => setShow(false)}>
{children}
</div>
</div>
);
}
Examples
ReactDOM.render(
<Tooltip text="Simple tooltip">
<button>Hover me!</button>
</Tooltip>,
document.getElementById('root')
);
This repository is a work in progress. If you want to contribute, please check the open issues to see where and how you can help out!
This README is built using markdown-builder.