Michio JP

Michio JP

1568688745

How to build an App With Just React Hooks

Originally published by Christopher T  at jsmanifest.com

React hooks are a new addition to the react library and has since been widely adopted by react developers by storm. These hooks allow you to write state logic and use other react features without having to write a class component.

In this article we will be building an app which I'll call Slotify, with just react hooks.

Slotify will provide a user interface to the user, presenting them a textarea that can take any blog post and insert quotes in them where newlines (\n) and word count will play a role in the quantity applied. A slotified post will have a minimum of one quote and a maximum of three quotes.

A quote and the author of the quote is allowed to be inserted wherever a slot is available. The user will be able to interact with the slot and type/paste in a quote/author of their choice. When they are done, they can click the save button and a refurbished blog post will be recreated that includes their quotes. This is the final version that the user is intended to use as their next blog post.

These are the hook apis we will be using: (Basically all of them)

  • React.useState
  • React.useEffect
  • React.useRef
  • React.useReducer
  • React.useCallback
  • React.useMemo
  • React.useImperativeHandle
  • React.useLayoutEffect
  • useSlotify (custom)

This is what we'll be building:

Without further ado, let's get started!

In this tutorial we are going to quickly generate a react project with create-react-app.

(If you want to get a copy of the repository from github, click here).

Go ahead and create a project using the command below. For this tutorial i’ll call our project build-with-hooks.

npx create-react-app build-with-hooks

Now go into the directory once it's done:

cd build-with-hooks

Inside the main entry src/index.js we're going to clean it up a bit so we can focus on the App component:

src/index.js
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import './index.css'
import * as serviceWorker from './serviceWorker'
ReactDOM.render(<App />, document.getElementById('root'))
serviceWorker.unregister()

Now go to src/App.js and lets start with rendering nothing:

import React from 'react'

function App() {
return null
}

export default App

The core functionality of our app is to allow a user to insert/write a blog post into some type of field so that quotes can be inserted.

To make sure that we stay positive and optimistic that we can do this, let’s just tackle down the core functionality first so that we know we’re in good shape.

That means we’re going to first make a button so that the user has the ability to start by clicking it. Then, we’re also going to create the textarea element so that the user can insert content into.

You may also like: Top 10 Custom React Hooks you Should Have in Your Toolbox

_

src/Button.js

import React from ‘react’

function Button({ children, …props }) {
return (
<button type=“button” {…props}>
{children}
</button>
)
}

export default Button

Inside index.css I applied some styling so that every button will have the same styles:

src/index.css

button {
border: 2px solid #eee;
border-radius: 4px;
padding: 8px 15px;
background: none;
color: #555;
cursor: pointer;
outline: none;
}

button:hover {
border: 2px solid rgb(224, 224, 224);
}
button:active {
border: 2px solid #aaa;
}

Lets proceed to create the textarea component. We’ll call it PasteBin:

src/PasteBin.js

import React from ‘react’

function PasteBin(props) {
return (
<textarea
style={{
width: ‘100%’,
margin: ‘12px 0’,
outline: ‘none’,
padding: 12,
border: ‘2px solid #eee’,
color: ‘#666’,
borderRadius: 4,
}}
rows={25}
{…props}
/>
)
}

export default PasteBin

Now we’re using inline styles because we want the styles to be included when the final content is generated. If we use pure CSS, only class name strings will be generated so the components would turn out styleless.

We’re going to create a react context to wrap this whole thing from the top so that we force all child components to have the ability to stay in sync with the rest of the components by using React.useContext

Create a Context.js file:

src/Context.js

import React from ‘react’

const Context = React.createContext()

export default Context

Now we are going to create Provider.js which will import Context.js and will hold all the logic in managing state:

src/Provider.js

import React from ‘react’
import Slot from ‘./Slot’
import { attachSlots, split } from ‘./utils’
import Context from ‘./Context’

const initialState = {
slotifiedContent: [],
}

function reducer(state, action) {
switch (action.type) {
case ‘set-slotified-content’:
return { …state, slotifiedContent: action.content }
default:
return state
}
}

function useSlotify() {
const [state, dispatch] = React.useReducer(reducer, initialState)
const textareaRef = React.useRef()

function slotify() {
let slotifiedContent, content
if (textareaRef && textareaRef.current) {
content = textareaRef.current.value
}
const slot = <Slot />
if (content) {
slotifiedContent = attachSlots(split(content), slot)
}
dispatch({ type: ‘set-slotified-content’, content: slotifiedContent })
}

return {
…state,
slotify,
textareaRef,
}
}

function Provider({ children }) {
return <Context.Provider value={useSlotify()}>{children}</Context.Provider>
}

export default Provider

I would like to take a moment to explain what this last code snippet is doing as it is very important. We would have used React.useState to manage our state, but when you think about what our app is going to do, you might realize that it isn’t just a single state because there are situations from both sides that need to be taken into consideration:

  1. When does the user want to slotify their blog post?
  2. When should we show them the final, refurbished content?
  3. How many slots should we insert into the blog post?
  4. When should we show or hide the slots?

Knowing this, we ought to use a React.useReducer to design our state to encapsulate state update logic into a single location, and so our first action is declared by adding the first switch case accessible by dispatching an action with type ‘set-slotified-content’.

The way we are going to insert slots into the blog post is grabbing a string and converting it to an array delimiting it by newlines ‘\n’ which is why the initial state declares slotifiedContent as an array, because that’s where we will putting our working data in.

We also see a textareaRef declared as we need to use it to grab a reference to our PasteBin component we created earlier. We could have made the textarea completely controlled, but the easiest and most performant way to communicate with that is to just grab a reference to the root textarea element because all we need to do is grab its value instead of setting states. This will be grabbed from using the ref prop on textarea later.

Our slotify function is invoked when the user presses the Start Quotifying button to slotify their blog post. The intention is to pop up a modal and show them the slots that they can enter their quote/authors into. We use the reference to the PasteBin component to grab the current value of the textarea and migrate the content to the modal.

We then use two utility functions, attachSlots and split to slotify the blog post and use that to set state.slotifiedContent so that our UI can pick it up and do their job.

We put attachSlots and split into a utils.js file as follows:

src/utils.js

export function attachSlots(content, slot) {
if (!Array.isArray(content)) {
throw new Error(‘content is not an array’)
}
let result = []
// Post is too short. Only provide a quote at the top
if (content.length <= 50) {
result = [slot, …content]
}
// Post is a little larger but 3 quotes is excessive. Insert a max of 2 quotes
else if (content.length > 50 && content.length < 100) {
result = [slot, …content, slot]
}
// Post should be large enough to look beautiful with 3 quotes inserted (top/mid/bottom)
else if (content.length > 100) {
const midpoint = Math.floor(content.length / 2)
result = [
slot,
…content.slice(0, midpoint),
slot,
…content.slice(midpoint),
slot,
]
}
return result
}

// Returns the content back as an array using a delimiter
export function split(content, delimiter = ‘\n’) {
return content.split(delimiter)
}

To apply the textareaRef to the PasteBin, we have to use React.useContext to get the React.useRef hook we declared earlier in useSlotify:

src/PasteBin.js

import React from ‘react’
import Context from ‘./Context’

function PasteBin(props) {
const { textareaRef } = React.useContext(Context)
return (
<textarea
ref={textareaRef}
style={{
width: ‘100%’,
margin: ‘12px 0’,
outline: ‘none’,
padding: 12,
border: ‘2px solid #eee’,
color: ‘#666’,
borderRadius: 4,
}}
rows={25}
{…props}
/>
)
}

export default PasteBin

The last thing we are missing is creating the <Slot /> component because we used it inside our context. This slot component is the component that takes in a quote and author from the user. This won’t be visible to the user right away because we are going to put it inside the modal component which will open only when the user clicks the Start Quotifying button.

This slot component will be a little tough, but i’ll explain what’s happening afterwards:

import React from ‘react’
import PropTypes from ‘prop-types’
import cx from ‘classnames’
import Context from ‘./Context’
import styles from ‘./styles.module.css’

function SlotDrafting({ quote, author, onChange }) {
const inputStyle = {
border: 0,
borderRadius: 4,
background: ‘none’,
fontSize: ‘1.2rem’,
color: ‘#fff’,
padding: ‘6px 15px’,
width: ‘100%’,
height: ‘100%’,
outline: ‘none’,
marginRight: 4,
}

return (
<div
style={{
display: ‘flex’,
justifyContent: ‘space-around’,
alignItems: ‘center’,
}}
>
<input
name=“quote”
type=“text”
placeholder=“Insert a quote”
style={{ flexGrow: 1, flexBasis: ‘70%’ }}
onChange={onChange}
value={quote}
className={styles.slotQuoteInput}
style={{ …inputStyle, flexGrow: 1, flexBasis: ‘60%’ }}
/>
<input
name=“author”
type=“text”
placeholder=“Author”
style={{ flexBasis: ‘30%’ }}
onChange={onChange}
value={author}
className={styles.slotQuoteInput}
style={{ …inputStyle, flexBasis: ‘40%’ }}
/>
</div>
)
}

function SlotStatic({ quote, author }) {
return (
<div style={{ padding: ‘12px 0’ }}>
<h2 style={{ fontWeight: 700, color: ‘#2bc7c7’ }}>{quote}</h2>
<p
style={{
marginLeft: 50,
fontStyle: ‘italic’,
color: ‘rgb(51, 52, 54)’,
opacity: 0.7,
textAlign: ‘right’,
}}
>
- {author}
</p>
</div>
)
}

function Slot({ input = ‘textfield’ }) {
const [quote, setQuote] = React.useState(‘’)
const [author, setAuthor] = React.useState(‘’)
const { drafting } = React.useContext(Context)

function onChange(e) {
if (e.target.name === ‘quote’) {
setQuote(e.target.value)
} else {
setAuthor(e.target.value)
}
}

let draftComponent, staticComponent

if (drafting) {
switch (input) {
case ‘textfield’:
draftComponent = (
<SlotDrafting onChange={onChange} quote={quote} author={author} />
)
break
default:
break
}
} else {
switch (input) {
case ‘textfield’:
staticComponent = <SlotStatic quote={quote} author={author} />
break
default:
break
}
}

return (
<div
style={{
color: ‘#fff’,
borderRadius: 4,
margin: ‘12px 0’,
outline: ‘none’,
transition: ‘all 0.2s ease-out’,
width: ‘100%’,
background: drafting
? ‘rgba(175, 56, 90, 0.2)’
: ‘rgba(16, 46, 54, 0.02)’,
boxShadow: drafting
? undefined
: ‘0 3px 15px 15px rgba(51, 51, 51, 0.03)’,
height: drafting ? 70 : ‘100%’,
minHeight: drafting ? ‘auto’ : 70,
maxHeight: drafting ? ‘auto’ : 100,
padding: drafting ? 8 : 0,
}}
>
<div
className={styles.slotInnerRoot}
style={{
transition: ‘all 0.2s ease-out’,
cursor: ‘pointer’,
width: ‘100%’,
height: ‘100%’,
padding: ‘0 6px’,
borderRadius: 4,
display: ‘flex’,
alignItems: ‘center’,
textTransform: ‘uppercase’,
justifyContent: drafting ? ‘center’ : ‘space-around’,
background: drafting
? ‘rgba(100, 100, 100, 0.35)’
: ‘rgba(100, 100, 100, 0.05)’,
}}
>
{drafting ? draftComponent : staticComponent}
</div>
</div>
)
}

Slot.defaultProps = {
slot: true,
}

Slot.propTypes = {
input: PropTypes.oneOf([‘textfield’]),
}

export default Slot

The most important part in this file is state.drafting. We didn’t declare this in the context yet, but its purpose is to give us a way to know when to show the user the slots as well as when to show them the final output. When state.drafting is true (which is going to be the default value), we will show them the slots which are the blocks that they can insert their quote and quote’s author to. When they click on the Save button, state.drafting will switch to false and we will use that to determine that they want to look at their final output.

We declared an input parameter with a default value of ‘textfield’ because in the future we might want to use other input types to let users insert quotes to besides typing (example: file inputs where we can let them upload images as quotes, etc). For this tutorial we’re only going to support ‘textfield’.

So when state.drafting is true<SlotDrafting /> is used by Slot, and when it’s false<SlotStatic /> is used. It’s better to separate this distinction into separate components so we don’t bloat components with a bunch of if/else conditionals.

Also, although we declared some inline styles for the quote/author input fields, we still applied className={styles.slotQuoteInput} so that we can style the placeholder since we won’t be able to do that with inline styles. (This is okay for the final refurbished content because inputs won’t even be generated)

Here is the css for that:

src/styles.module.css

.slotQuoteInput::placeholder {
color: #fff;
font-size: 0.9rem;
}

Let’s go back and declare the drafting state to the context:

src/Provider.js

import React from ‘react’
import Slot from ‘./Slot’
import { attachSlots, split } from ‘./utils’
import Context from ‘./Context’

const initialState = {
slotifiedContent: [],
drafting: true,
}

function reducer(state, action) {
switch (action.type) {
case ‘set-slotified-content’:
return { …state, slotifiedContent: action.content }
case ‘set-drafting’:
return { …state, drafting: action.drafting }
default:
return state
}
}

function useSlotify() {
const [state, dispatch] = React.useReducer(reducer, initialState)
const textareaRef = React.useRef()

function onSave() {
if (state.drafting) {
setDrafting(false)
}
}

function setDrafting(drafting) {
if (drafting === undefined) return
dispatch({ type: ‘set-drafting’, drafting })
}

function slotify() {
let slotifiedContent, content
if (textareaRef && textareaRef.current) {
content = textareaRef.current.value
}
const slot = <Slot />
if (content && typeof content === ‘string’) {
slotifiedContent = attachSlots(split(content), slot)
}
dispatch({ type: ‘set-slotified-content’, content: slotifiedContent })
}

return {
…state,
slotify,
onSave,
setDrafting,
textareaRef,
}
}

function Provider({ children }) {
return <Context.Provider value={useSlotify()}>{children}</Context.Provider>
}

export default Provider

Now finally lets put this into the App.js component so we can see what this all looks like so far:

(Note: in this example I used a modal component from semantic-ui-react which is not required for the modal. You can use any modal or create a plain modal of your own using the react portal api):

src/App.js

import React from ‘react’
import { Modal } from ‘semantic-ui-react’
import Button from ‘./Button’
import Context from ‘./Context’
import Provider from ‘./Provider’
import PasteBin from ‘./PasteBin’
import styles from ‘./styles.module.css’

// Purposely call each fn without args since we don’t need them
const callFns = (…fns) => () => fns.forEach((fn) => fn && fn())

const App = () => {
const {
modalOpened,
slotifiedContent = [],
slotify,
onSave,
openModal,
closeModal,
} = React.useContext(Context)

return (
<div
style={{
padding: 12,
boxSizing: ‘border-box’,
}}
>
<Modal
open={modalOpened}
trigger={
<Button type=“button” onClick={callFns(slotify, openModal)}>
Start Quotifying
</Button>
}
>
<Modal.Content
style={{
background: ‘#fff’,
padding: 12,
color: ‘#333’,
width: ‘100%’,
}}
>
<div>
<Modal.Description>
{slotifiedContent.map((content) => (
<div style={{ whiteSpace: ‘pre-line’ }}>{content}</div>
))}
</Modal.Description>
</div>
<Modal.Actions>
<Button type=“button” onClick={onSave}>
SAVE
</Button>
</Modal.Actions>
</Modal.Content>
</Modal>
<PasteBin onSubmit={slotify} />
</div>
)
}

export default () => (
<Provider>
<App />
</Provider>
)

Before we start up our server we need to declare the modal states (open/close):

src/Provider.js

import React from ‘react’
import Slot from ‘./Slot’
import { attachSlots, split } from ‘./utils’
import Context from ‘./Context’

const initialState = {
slotifiedContent: [],
drafting: true,
modalOpened: false,
}

function reducer(state, action) {
switch (action.type) {
case ‘set-slotified-content’:
return { …state, slotifiedContent: action.content }
case ‘set-drafting’:
return { …state, drafting: action.drafting }
case ‘open-modal’:
return { …state, modalOpened: true }
case ‘close-modal’:
return { …state, modalOpened: false }
default:
return state
}
}

function useSlotify() {
const [state, dispatch] = React.useReducer(reducer, initialState)
const textareaRef = React.useRef()

function onSave() {
if (state.drafting) {
setDrafting(false)
}
}

function openModal() {
dispatch({ type: ‘open-modal’ })
}

function closeModal() {
dispatch({ type: ‘close-modal’ })
}

function setDrafting(drafting) {
if (typeof drafting !== ‘boolean’) return
dispatch({ type: ‘set-drafting’, drafting })
}

function slotify() {
let slotifiedContent, content
if (textareaRef && textareaRef.current) {
content = textareaRef.current.value
}
const slot = <Slot />
if (content && typeof content === ‘string’) {
slotifiedContent = attachSlots(split(content), slot)
}
if (!state.drafting) {
setDrafting(true)
}
dispatch({ type: ‘set-slotified-content’, content: slotifiedContent })
}

return {
…state,
slotify,
onSave,
setDrafting,
textareaRef,
openModal,
closeModal,
}
}

function Provider({ children }) {
return <Context.Provider value={useSlotify()}>{children}</Context.Provider>
}

export default Provider

And here’s what we should have so far:

(Note: The SAVE button is closing the modal in the image, but that was a minor error. It should not close the modal)

Now we’re going to change PasteBin a little to declare a new api using React.useImperativeHandle for the textarea so that we can use it in useSlotify and we don’t bloat the hook with a bunch of functions but instead provide back an encapsulated api:

src/PasteBin.js

import React from ‘react’
import Context from ‘./Context’

function PasteBin(props) {
const { textareaRef, textareaUtils } = React.useContext(Context)

React.useImperativeHandle(textareaUtils, () => ({
copy: () => {
textareaRef.current.select()
document.execCommand(‘copy’)
textareaRef.current.blur()
},
getText: () => {
return textareaRef.current.value
},
}))

return (
<textarea
ref={textareaRef}
style={{
width: ‘100%’,
margin: ‘12px 0’,
outline: ‘none’,
padding: 12,
border: ‘2px solid #eee’,
color: ‘#666’,
borderRadius: 4,
}}
rows={25}
{…props}
/>
)
}

export default PasteBin

textareaUtils will also be a React.useRef which will be placed right next to textareaRef in the useSlotify hook:

const [state, dispatch] = React.useReducer(reducer, initialState)
const textareaRef = React.useRef()
const textareaUtils = React.useRef()

We will use this new api in the slotify function:

src/Provider.js

function slotify() {
let slotifiedContent, content
if (textareaRef && textareaRef.current) {
textareaUtils.current.copy()
textareaUtils.current.blur()
content = textareaUtils.current.getText()
}
const slot = <Slot />
if (content && typeof content === ‘string’) {
slotifiedContent = attachSlots(split(content), slot)
}
if (!state.drafting) {
setDrafting(true)
}
dispatch({ type: ‘set-slotified-content’, content: slotifiedContent })
}

Now the next thing we are going to do is that when the user is looking at the slots and we detect that they haven’t inserted an author yet, we flash that element to bring more of their attention.

For this, we are going to use React.useLayoutEffect inside the SlotDrafting component because SlotDrafting contains the author input:

src/Slot.js

function SlotDrafting({ quote, author, onChange }) {
const authorRef = React.createRef()

React.useLayoutEffect(() => {
const elem = authorRef.current
if (!author) {
elem.classList.add(styles.slotQuoteInputAttention)
} else if (author) {
elem.classList.remove(styles.slotQuoteInputAttention)
}
}, [author, authorRef])

const inputStyle = {
border: 0,
borderRadius: 4,
background: ‘none’,
fontSize: ‘1.2rem’,
color: ‘#fff’,
padding: ‘6px 15px’,
width: ‘100%’,
height: ‘100%’,
outline: ‘none’,
marginRight: 4,
}

return (
<div
style={{
display: ‘flex’,
justifyContent: ‘space-around’,
alignItems: ‘center’,
}}
>
<input
name=“quote”
type=“text”
placeholder=“Insert a quote”
onChange={onChange}
value={quote}
className={styles.slotQuoteInput}
style={{ …inputStyle, flexGrow: 1, flexBasis: ‘60%’ }}
/>
<input
ref={authorRef}
name=“author”
type=“text”
placeholder=“Author”
onChange={onChange}
value={author}
className={styles.slotQuoteInput}
style={{ …inputStyle, flexBasis: ‘40%’ }}
/>
</div>
)
}

We probably didn’t need the use of useLayoutEffect here, but it’s just for demonstration. It’s known to be a good option for style updates. since the hook is invoked after the dom is mounted and has had its mutations updated. The reason it’s good for styling reasons is because it’s invoked before the next browser repaint whereas the useEffect hook is invoked afterwards–which can cause a sluggy flashy effect in the UI.

styles:

src/styles.module.css

.slotQuoteInputAttention {
transition: all 1s ease-out;
animation: emptyAuthor 3s infinite;
border: 1px solid #91ffde;
}

.slotQuoteInputAttention::placeholder {
color: #91ffde;
}

.slotQuoteInputAttention:hover,
.slotQuoteInputAttention:focus,
.slotQuoteInputAttention:active {
transform: scale(1.1);
}

@keyframes emptyAuthor {
0% {
opacity: 1;
}
50% {
opacity: 0;
}
100% {
opacity: 1;
}
}

On the bottom of the modal we put a SAVE button which will invoke onSave from useSlotify. When the user clicks this, the slots will convert to finalized slots (when drafting === false). We will also render a button nearby that will copy the source code in HTML to their clipboard so that they can paste the content on their blog post.

So far, here is what we have:

Everything will stay the same, except now we work with CSS class names. For the new css class names they are suffixed with Static to indicate that they are used when drafting === false. Here is a slight change to the Slot component to accomodate the CSS changes:

src/Slot.js

function Slot({ input = ‘textfield’ }) {
const [quote, setQuote] = React.useState(‘’)
const [author, setAuthor] = React.useState(‘’)
const { drafting } = React.useContext(Context)

function onChange(e) {
if (e.target.name === ‘quote’) {
setQuote(e.target.value)
} else {
setAuthor(e.target.value)
}
}

let draftComponent, staticComponent

if (drafting) {
switch (input) {
case ‘textfield’:
draftComponent = (
<SlotDrafting onChange={onChange} quote={quote} author={author} />
)
break
default:
break
}
} else {
switch (input) {
case ‘textfield’:
staticComponent = <SlotStatic quote={quote} author={author} />
break
default:
break
}
}

return (
<div
style={{
color: ‘#fff’,
borderRadius: 4,
margin: ‘12px 0’,
outline: ‘none’,
transition: ‘all 0.2s ease-out’,
width: ‘100%’,
background: drafting
? ‘rgba(175, 56, 90, 0.2)’
: ‘rgba(16, 46, 54, 0.02)’,
boxShadow: drafting
? undefined
: ‘0 3px 15px 15px rgba(51, 51, 51, 0.03)’,
height: drafting ? 70 : ‘100%’,
minHeight: drafting ? ‘auto’ : 70,
maxHeight: drafting ? ‘auto’ : 100,
padding: drafting ? 8 : 0,
}}
className={cx({
[styles.slotRoot]: drafting,
[styles.slotRootStatic]: !drafting,
})}
>
<div
className={styles.slotInnerRoot}
style={{
transition: ‘all 0.2s ease-out’,
cursor: ‘pointer’,
width: ‘100%’,
height: ‘100%’,
padding: ‘0 6px’,
borderRadius: 4,
display: ‘flex’,
alignItems: ‘center’,
textTransform: ‘uppercase’,
justifyContent: drafting ? ‘center’ : ‘space-around’,
background: drafting
? ‘rgba(100, 100, 100, 0.35)’
: ‘rgba(100, 100, 100, 0.05)’,
}}
>
{drafting ? draftComponent : staticComponent}
</div>
</div>
)
}

And here are the newly added CSS styles:

.slotRoot:hover {
background: rgba(245, 49, 104, 0.3) !important;
}

.slotRootStatic:hover {
background: rgba(100, 100, 100, 0.07) !important;
}

.slotInnerRoot:hover {
filter: brightness(80%);
}

Here is what our app looks like now:

The last thing we need to do is add a Close button to close the modal, and a Copy button to copy the source code of their finalized blog post.

Adding the Close button is easy. Just add this button next to the Save button. The Copy button will be placed next to the Close button. These buttons will be given some onClick handlers:

src/App.js

<Modal.Actions>
<Button type=“button” onClick={onSave}>
SAVE
</Button>
&nbsp;
<Button type=“button” onClick={closeModal}>
CLOSE
</Button>
&nbsp;
<Button type=“button” onClick={onCopyFinalDraft}>
COPY
</Button>
</Modal.Actions>

We should be done when we implement the onCopyFinalContent function, but we’re not yet. We’re missing one last step. When we copy the finalized content, which part of the UI are we copying? We can’t be copying the entire modal because we don’t want the SAVECLOSE and COPY buttons in our blog posts or it would look awfully awkward. We have to make another React.useRef and use that to attach to a specific element that only includes the content we want.

This is why we *used inline styles and not entirely CSS classes because we want the styles to be included in the refurbished version.

Declare modalRef in useSlotify:

const textareaRef = React.useRef()
const textareaUtils = React.useRef()
const modalRef = React.useRef()

Attach it to the element that will only contain the content:

src/App.js

const ModalContent = ({ innerRef, …props }) => (
<div ref={innerRef} {…props} />
)

const App = () => {
const {
modalOpened,
slotifiedContent = [],
slotify,
onSave,
openModal,
closeModal,
modalRef,
onCopyFinalContent,
} = React.useContext(Context)

return (
<div
style={{
padding: 12,
boxSizing: ‘border-box’,
}}
>
<Modal
open={modalOpened}
trigger={
<Button type=“button” onClick={callFns(slotify, openModal)}>
Start Quotifying
</Button>
}
style={{
background: ‘#fff’,
padding: 12,
color: ‘#333’,
width: ‘100%’,
}}
>
<Modal.Content>
<Modal.Description as={ModalContent} innerRef={modalRef}>
{slotifiedContent.map((content) => (
<div style={{ whiteSpace: ‘pre-line’ }}>{content}</div>
))}
</Modal.Description>
<Modal.Actions>
<Button type=“button” onClick={onSave}>
SAVE
</Button>
&nbsp;
<Button type=“button” onClick={closeModal}>
CLOSE
</Button>
&nbsp;
<Button type=“button” onClick={onCopyFinalContent}>
COPY
</Button>
</Modal.Actions>
</Modal.Content>
</Modal>
<PasteBin onSubmit={slotify} />
</div>
)
}

Note: We declared the ModalContent function component outside the App component because we want the reference to stay the same. If we use it inside App.js, then the component will be re-rendered and all of the quotes/author values will be reset since the onSave function updates the state.

And finally, onCopyFinalDraft will be placed inside the useSlotify hook that will use the modalRef ref:

src/Provider.js

function onCopyFinalContent() {
const html = modalRef.current.innerHTML
const inputEl = document.createElement(‘textarea’)
document.body.appendChild(inputEl)
inputEl.value = html
inputEl.select()
document.execCommand(‘copy’)
document.body.removeChild(inputEl)
}

And we are done!

Here is our app now:

Conclusion

And that concludes the end of this post! I hope you found it useful and look out for more in the future!

Further Reading

Top 10 Custom React Hooks you Should Have in Your Toolbox

How to Replace Redux with React Hooks and the Context API

The Definitive React Hooks Cheatsheet

React Hooks Tutorial for Beginners: Getting Started With React Hooks

Originally published by Christopher T  at jsmanifest.com

===================================================================

Thanks for reading :heart: If you liked this post, share it with all of your programming buddies! Follow me on Facebook | Twitter

#reactjs #javascript #web-development

What is GEEK

Buddha Community

How to build an App With Just React Hooks
Autumn  Blick

Autumn Blick

1598839687

How native is React Native? | React Native vs Native App Development

If you are undertaking a mobile app development for your start-up or enterprise, you are likely wondering whether to use React Native. As a popular development framework, React Native helps you to develop near-native mobile apps. However, you are probably also wondering how close you can get to a native app by using React Native. How native is React Native?

In the article, we discuss the similarities between native mobile development and development using React Native. We also touch upon where they differ and how to bridge the gaps. Read on.

A brief introduction to React Native

Let’s briefly set the context first. We will briefly touch upon what React Native is and how it differs from earlier hybrid frameworks.

React Native is a popular JavaScript framework that Facebook has created. You can use this open-source framework to code natively rendering Android and iOS mobile apps. You can use it to develop web apps too.

Facebook has developed React Native based on React, its JavaScript library. The first release of React Native came in March 2015. At the time of writing this article, the latest stable release of React Native is 0.62.0, and it was released in March 2020.

Although relatively new, React Native has acquired a high degree of popularity. The “Stack Overflow Developer Survey 2019” report identifies it as the 8th most loved framework. Facebook, Walmart, and Bloomberg are some of the top companies that use React Native.

The popularity of React Native comes from its advantages. Some of its advantages are as follows:

  • Performance: It delivers optimal performance.
  • Cross-platform development: You can develop both Android and iOS apps with it. The reuse of code expedites development and reduces costs.
  • UI design: React Native enables you to design simple and responsive UI for your mobile app.
  • 3rd party plugins: This framework supports 3rd party plugins.
  • Developer community: A vibrant community of developers support React Native.

Why React Native is fundamentally different from earlier hybrid frameworks

Are you wondering whether React Native is just another of those hybrid frameworks like Ionic or Cordova? It’s not! React Native is fundamentally different from these earlier hybrid frameworks.

React Native is very close to native. Consider the following aspects as described on the React Native website:

  • Access to many native platforms features: The primitives of React Native render to native platform UI. This means that your React Native app will use many native platform APIs as native apps would do.
  • Near-native user experience: React Native provides several native components, and these are platform agnostic.
  • The ease of accessing native APIs: React Native uses a declarative UI paradigm. This enables React Native to interact easily with native platform APIs since React Native wraps existing native code.

Due to these factors, React Native offers many more advantages compared to those earlier hybrid frameworks. We now review them.

#android app #frontend #ios app #mobile app development #benefits of react native #is react native good for mobile app development #native vs #pros and cons of react native #react mobile development #react native development #react native experience #react native framework #react native ios vs android #react native pros and cons #react native vs android #react native vs native #react native vs native performance #react vs native #why react native #why use react native

What are hooks in React JS? - INFO AT ONE

In this article, you will learn what are hooks in React JS? and when to use react hooks? React JS is developed by Facebook in the year 2013. There are many students and the new developers who have confusion between react and hooks in react. Well, it is not different, react is a programming language and hooks is a function which is used in react programming language.
Read More:- https://infoatone.com/what-are-hooks-in-react-js/

#react #hooks in react #react hooks example #react js projects for beginners #what are hooks in react js? #when to use react hooks

Top 10 React Native App Development Companies in USA

React Native is the most popular dynamic framework that provides the opportunity for Android & iOS users to download and use your product. Finding a good React Native development company is incredibly challenging. Use our list as your go-to resource for React Native app development Companies in USA.

List of Top-Rated React Native Mobile App Development Companies in USA:

  1. AppClues Infotech
  2. WebClues Infotech
  3. AppClues Studio
  4. WebClues Global
  5. Data EximIT
  6. Apptunix
  7. BHW Group
  8. Willow Tree:
  9. MindGrub
  10. Prismetric

A Brief about the company details mentioned below:

1. AppClues Infotech
As a React Native Mobile App Development Company in USA, AppClues Infotech offers user-centered mobile app development for iOS & Android. Since their founding in 2014, their React Native developers create beautiful mobile apps.

They have a robust react native app development team that has high knowledge and excellent strength of developing any type of mobile app. They have successfully delivered 450+ mobile apps as per client requirements and functionalities.
Website: https://www.appcluesinfotech.com/

2. WebClues Infotech
WebClues Infotech is the Top-Notch React Native mobile app development company in USA & offering exceptional service worldwide. Since their founding in 2014, they have completed 950+ web & mobile apps projects on time.

They have the best team of developers who has an excellent knowledge of developing the most secure, robust & Powerful React Native Mobile Apps. From start-ups to enterprise organizations, WebClues Infotech provides top-notch React Native App solutions that meet the needs of their clients.
Website: https://www.webcluesinfotech.com/

3. AppClues Studio
AppClues Studio is one of the top React Native mobile app development company in USA and offers the best service worldwide at an affordable price. They have a robust & comprehensive team of React Native App developers who has high strength & extensive knowledge of developing any type of mobile apps.
Website: https://www.appcluesstudio.com/

4. WebClues Global
WebClues Global is one of the best React Native Mobile App Development Company in USA. They provide low-cost & fast React Native Development Services and their React Native App Developers have a high capability of serving projects on more than one platform.

Since their founding in 2014, they have successfully delivered 721+ mobile app projects accurately. They offer versatile React Native App development technology solutions to their clients at an affordable price.
Website: https://www.webcluesglobal.com/

5. Data EximIT
Hire expert React Native app developer from top React Native app development company in USA. Data EximIT is providing high-quality and innovative React Native application development services and support for your next projects. The company has been in the market for more than 8 years and has already gained the trust of 553+ clients and completed 1250+ projects around the globe.

They have a large pool of React Native App developers who can create scalable, full-fledged, and appealing mobile apps to meet the highest industry standards.
Website: https://www.dataeximit.com/

6. Apptunix
Apptunix is the best React Native App Development Company in the USA. It was established in 2013 and vast experience in developing React Native apps. After developing various successful React Native Mobile Apps, the company believes that this technology helps them incorporate advanced features in mobile apps without influencing the user experience.
Website: https://www.apptunix.com/

7. BHW Group
BHW Group is a Top-Notch React Native Mobile App Development Company in the USA. The company has 13+ years of experience in providing qualitative app development services to clients worldwide. They have a compressive pool of React Native App developers who can create scalable, full-fledged, and creative mobile apps to meet the highest industry standards.
Website: https://thebhwgroup.com/

8. Willow Tree:
Willow Tree is the Top-Notch React Native Mobile App Development Company in the USA & offering exceptional React Native service. They have the best team of developers who has an excellent knowledge of developing the most secure, robust & Powerful React Native Mobile Apps. From start-ups to enterprise organizations, Willow Tree has top-notch React Native App solutions that meet the needs of their clients.
Website: https://willowtreeapps.com/

9. MindGrub
MindGrub is a leading React Native Mobile App Development Company in the USA. Along with React Native, the company also works on other emerging technologies like robotics, augmented & virtual reality. The Company has excellent strength and the best developers team for any type of React Native mobile apps. They offer versatile React Native App development technology solutions to their clients.
Website: https://www.mindgrub.com/

10. Prismetric
Prismetric is the premium React Native Mobile App Development Company in the USA. They provide fast React Native Development Services and their React Native App Developers have a high capability of serving projects on various platforms. They focus on developing customized solutions for specific business requirements. Being a popular name in the React Native development market, Prismetric has accumulated a specialty in offering these services.
Website: https://www.prismetric.com/

#top rated react native app development companies in usa #top 10 react native app development companies in usa #top react native app development companies in usa #react native app development technologies #react native app development #hire top react native app developers in usa

Fredy  Larson

Fredy Larson

1595059664

How long does it take to develop/build an app?

With more of us using smartphones, the popularity of mobile applications has exploded. In the digital era, the number of people looking for products and services online is growing rapidly. Smartphone owners look for mobile applications that give them quick access to companies’ products and services. As a result, mobile apps provide customers with a lot of benefits in just one device.

Likewise, companies use mobile apps to increase customer loyalty and improve their services. Mobile Developers are in high demand as companies use apps not only to create brand awareness but also to gather information. For that reason, mobile apps are used as tools to collect valuable data from customers to help companies improve their offer.

There are many types of mobile applications, each with its own advantages. For example, native apps perform better, while web apps don’t need to be customized for the platform or operating system (OS). Likewise, hybrid apps provide users with comfortable user experience. However, you may be wondering how long it takes to develop an app.

To give you an idea of how long the app development process takes, here’s a short guide.

App Idea & Research

app-idea-research

_Average time spent: two to five weeks _

This is the initial stage and a crucial step in setting the project in the right direction. In this stage, you brainstorm ideas and select the best one. Apart from that, you’ll need to do some research to see if your idea is viable. Remember that coming up with an idea is easy; the hard part is to make it a reality.

All your ideas may seem viable, but you still have to run some tests to keep it as real as possible. For that reason, when Web Developers are building a web app, they analyze the available ideas to see which one is the best match for the targeted audience.

Targeting the right audience is crucial when you are developing an app. It saves time when shaping the app in the right direction as you have a clear set of objectives. Likewise, analyzing how the app affects the market is essential. During the research process, App Developers must gather information about potential competitors and threats. This helps the app owners develop strategies to tackle difficulties that come up after the launch.

The research process can take several weeks, but it determines how successful your app can be. For that reason, you must take your time to know all the weaknesses and strengths of the competitors, possible app strategies, and targeted audience.

The outcomes of this stage are app prototypes and the minimum feasible product.

#android app #frontend #ios app #minimum viable product (mvp) #mobile app development #web development #android app development #app development #app development for ios and android #app development process #ios and android app development #ios app development #stages in app development

Juned Ghanchi

1621573085

React Native App Developers India, React Native App Development Company

Expand your user base by using react-native apps developed by our expert team for various platforms like Android, Android TV, iOS, macOS, tvOS, the Web, Windows, and UWP.

We help businesses to scale up the process and achieve greater performance by providing the best react native app development services. Our skilled and experienced team’s apps have delivered all the expected results for our clients across the world.

To achieve growth for your business, hire react native app developers in India. You can count on us for all the technical services and support.

#react native app development company india #react native app developers india #hire react native developers india #react native app development company #react native app developers #hire react native developers