Build a modal com­po­nent

Learn how to cre­ate a sim­ple, us­able modal com­po­nent lever­ag­ing the power of Re­act’s por­tal func­tion­al­ity

Web Designer - - Contents -

Learn how to cre­ate a sim­ple, us­able modal com­po­nent lever­ag­ing the power of Re­act’s por­tal func­tion­al­ity

Re­act is one of the most pop­u­lar Javascript frame­works in use to­day. Cre­ated by Face­book to help it build user in­ter­faces, Re­act brings sim­plic­ity, speed, and scal­a­bil­ity to web projects.

In this tu­to­rial, we’re go­ing to use Re­act to cre­ate a sim­ple modal com­po­nent, which is op­ti­mised for both desk­top and mo­bile de­vices. To en­hance the modal, we’ll be us­ing Re­act’s rel­a­tively new and very use­ful por­tal func­tion­al­ity, which en­ables us to ren­der an el­e­ment out­side of the DOM hi­er­ar­chy of its par­ent com­po­nent, whilst still be­hav­ing like a nor­mal Re­act child.

To be­gin, down­load the tu­to­rial files from Filesilo, then open the ‘web­site-tem­plate’ di­rec­tory in your pre­ferred text ed­i­tor. In Ter­mi­nal, ‘CD’ into ‘web­site-tem­plate’ and then run ‘npm in­stall’ to in­stall all of the project’s de­pen­den­cies. We can then start a de­vel­op­ment server by run­ning the ‘npm run start’ com­mand, en­abling us to view the web­site at ‘lo­cal­host:3000’. As we make changes, this page should au­to­mat­i­cally re­fresh, so help­ing us to en­sure that we’re al­ways look­ing at the most up-to-date ver­sion.

1. Cre­ate com­po­nent struc­ture

In ‘src/com­po­nents’, cre­ate a new file called ‘Modal.js’. All the CSS for the modal is al­ready present in ‘_Mo­dal.scss’, en­abling us to fo­cus purely on build­ing the Re­act com­po­nent. Within the new file, we’ll cre­ate a new Re­act com­po­nent called ‘Modal’ by im­port­ing and then ex­tend­ing Re­act’s com­po­nent class. im­port Re­act from ‘re­act’; im­port Close from ‘../as­sets/img/close.svg’; ex­port de­fault class Modal ex­tends Re­act. Com­po­nent { con­struc­tor(props) { su­per(props);

} }

2. Val­i­date props

Next, we’ll set some val­i­da­tion rules for prop­er­ties, which our Modal will ac­cept when used in par­ent com­po­nents. Be­low your im­port Re­act state­ment, add “im­port Prop­types from ‘prop-types’” and then be­low the con­struc­tor func­tion in the com­po­nent it­self, add the fol­low­ing snip­pet: static prop­types = { ac­tive: Prop­types.bool.is­re­quired, fo­cuse­lem: Prop­types.string, han­dle­close: Prop­types.func.is­re­quired, re­turn­fo­cuse­lem: Prop­types.ob­ject, ti­tle: Prop­types.string }

3. Cre­ate modal JSX

Cre­ate a new func­tion within the com­po­nent called ‘modal­con­tent’. We’ll use this to store the JSX (AKA: the HTML) of our modal. The use of ‘this.props.chil­dren’ en­ables us to pass the modal its con­tent like a reg­u­lar HTML el­e­ment with­out us hav­ing to mod­ify the com­po­nent di­rectly. modal­con­tent = () => { re­turn (

<div class­name=’c-modal’>

<div class­name=’c-modal__wrap­per’>

<div class­name=’c-modal__ti­tle-wrap­per’> {this.props.ti­tle ? <h1 class­name =’t-beta c-modal__ti­tle’>{this.props. ti­tle}</h1> : ‘’}

<img src={close} class­name=’c-modal__ close’ tabindex=’0’ alt=’close Modal’ />

</div>

<div class­name=’c-modal__box’>

<div class­name=’c-modal__­con­tent’> {this.props.chil­dren}

</div>

</div>

</div>

</div>

)}

4. Ren­der modal – part 1

For now, let’s ren­der the modal to the screen so we can see what we’re work­ing with. In the modal com­po­nent, cre­ate a new func­tion called ‘ren­der’ and pass it our ‘modal­con­tent’ func­tion. Add the be­low as the last func­tion of the Re­act com­po­nent: ren­der() {

re­turn this.modal­con­tent(); }

5. Ren­der modal – part 2

Open ‘Call­toac­tion.js’. This is the par­ent com­po­nent, which will store our new modal. First off, let’s im­port the modal to this com­po­nent by adding “im­port Modal from ‘./Modal’;” to its list of im­ports. Then within this com­po­nents ren­der func­tion, just be­fore the clos­ing ‘div’ el­e­ment, add the fol­low­ing snip­pet:

<Modal ti­tle=’new York Hol­i­day’>

<App­form />

</Modal>

6. Add por­tal mount point

You should now be able to see the modal. Since it’s still lo­cated within the DOM tree of its par­ent com­po­nent, the par­ent styles are in­ter­fer­ing with its dis­play. One way to fix this is to ren­der the modal right at the top of the DOM tree, just af­ter the open­ing ‘body’ el­e­ment. This can be done us­ing Re­act Por­tals, which pro­vide a way to ren­der chil­dren into a DOM node that ex­ists out­side the hi­er­ar­chy of the par­ent com­po­nent. Let’s start by adding a new el­e­ment to ‘App.js’, the top-level Re­act com­po­nent, to hold the modal. Add the fol­low­ing snip­pet just af­ter this

com­po­nent’s open­ing ‘div’ at­tribute: <div id=’modal-root’ />

7. Cre­ate the por­tal

Next, back in ‘Modal.js’, add “im­port { cre­atepor­tal } from ‘re­act-dom’;” just af­ter the Re­act im­port. Then in the ‘con­struc­tor’ func­tion, just af­ter the ‘su­per’ func­tion, add “this.el = doc­u­ment.cre­ateele­ment(‘div’);” This is the wrap­per el­e­ment, which the ‘cre­atepor­tal’ func­tion re­quires to hold our modal con­tent. Fi­nally, re­place the ex­ist­ing ‘ren­der’ func­tion with the snip­pet be­low to ren­der the modal through the con­text of a Re­act por­tal: ren­der() { re­turn cre­atepor­tal( this.modal­con­tent(), this.el

); }

8. Mount the por­tal

You will no­tice the modal has van­ished. This is be­cause we still haven’t mounted the modal por­tal into the ‘div’ el­e­ment we cre­ated at the top of the DOM tree. Add the be­low snip­pet to the ‘modal’ com­po­nent to make it ap­pear again: com­po­nent­did­mount() {

doc­u­ment.getele­ment­byid(‘modal-root’). ap­pend­child(this.el);

}

9. Track­ing modal state

At the mo­ment our modal is al­ways show­ing. Ob­vi­ously this isn’t ideal, so let’s build in some tog­gle func­tion­al­ity. Open ‘Call­toac­tion.js’, and add the fol­low­ing snip­pet just be­fore its ‘ren­der’ func­tion. This adds two things: a state ob­ject con­tain­ing a Boolean to track if the modal should be show­ing, and a func­tion to set this Boolean to ‘true’, which should also trig­ger the modal. state = { modalac­tive: false } show­modal = () => { this.set­state({ modalac­tive: true }) }

10. Pass state to modal

We now need to pass the state ob­ject to the modal so it knows when it should be show­ing, or not. To do so, add ‘ac­tive={this.state.modalac­tive}’ to the open­ing <Modal> tag. Then, still within ‘Call­toac­tion.js’, re­place the ‘Claim Hol­i­day’ but­ton com­po­nent in­stance with the ver­sion in the snip­pet be­low. What this does is pass our ‘show­modal’ func­tion to the but­ton, so when it’s clicked, the ‘modalac­tive’ vari­able in the state ob­ject is set to ‘true’. We wrap our ‘show­modal’ func­tion in an­other func­tion to stop it from im­me­di­ately fir­ing on ren­der.

<But­ton han­dleclick={() => this. show­modal()}>claim Hol­i­day</but­ton>

11. Con­di­tional ren­der­ing

In ‘Modal.js’, let’s now change the ‘ren­der’ func­tion so the modal only ever ap­pears in the DOM if its ‘ac­tive’ prop is true. ren­der() { if(this.props.ac­tive) { re­turn cre­atepor­tal( this.modal­con­tent(), this.el

);

} else { re­turn false;

} }

12. Cre­ate close modal func­tion

Now we’ll look at clos­ing the modal when its ‘X’ icon is clicked. In the ‘Call­toac­tion.js’ com­po­nent, du­pli­cate the ‘show­modal’ func­tion, re­name it ‘close­modal’, then make it set the ‘modalac­tive’ vari­able to ‘false’. Next, we should pass this func­tion to the modal so it can be called from within it. To do so, pass it as the ‘han­dle­close’ prop as in the snip­pet be­low:

<Modal han­dle­close={() => this.close­modal()} ac­tive={this.state.modalac­tive} ti­tle=’new York Hol­i­day’ >

13. At­tach the close func­tion

Next, within ‘Modal.js’, add ‘onclick={this.props. han­dle­close}’ to the ‘img’ el­e­ment, so that our passed func­tion will trig­ger on click­ing the ‘X’ icon. We should also con­sider peo­ple who nav­i­gate us­ing key­boards. Add the be­low func­tion to the modal com­po­nent, and then add ‘on­key­press={(e) => this.han­dlekey­press(e)}’ to the ‘X’ icon ‘img’ el­e­ment. This will add func­tion­al­ity so that when the ‘X’ icon is in fo­cus, and the user presses En­ter, the modal closes. han­dlekey­press = (e) => { if(e.which === 13) { this.props.han­dle­close();

} }

14. Add more ways to close modal

We should also add ad­di­tional func­tion­al­ity so the modal closes if the user clicks the dark­ened modal back­ground, or presses the Esc key. Let’s cover the for­mer first. Add the snip­pet be­low to the modal com­po­nent and then add ‘onclick={(e) => this.han­dleclick(e)}’ to the ‘c-modal’ el­e­ment. What this does is lis­ten for clicks on the modal el­e­ment and then fig­ures out if it was on the modal box, or the back­ground, clos­ing the com­po­nent if it’s the lat­ter. We have to use a ‘try/catch’ here for In­ter­net Ex­plorer com­pat­i­bil­ity pur­poses.

han­dleclick = (e) => {

Newspapers in English

Newspapers from UK

© PressReader. All rights reserved.