با استفاده از React، یک دکمه Toggle سفارشی بسازید

گردآوری و تالیف : عرفان کاکایی
تاریخ انتشار : 23 آبان 1397
دسته بندی ها : react

ساخت وب‌اپلیکیشن‌ها معمولا شامل ساخت مقرراتی برای تعاملات کاربری است. یکی از راه‌های اصلی برای ساخت این مقررات برای تعاملات کاربری، از طریق فرم‌ها است. کامپوننت‌های فرم مختلف، برای این وجود دارند که انواع مختلف ورودی را از کاربر بگیرند. برای مثال، یک کامپوننت پسوورد اطلاعات حساسی را از کاربر می‌گیرد و آن‌ها را می‌پوشاند تا نمایان نباشند.

اکثر مواقع، اطلاعاتی که باید از یک کاربر بگیرید، به مانند boolean‌ هستند. مثلا: yes یا no، true یا false، enable یا disable، on‌ یا off و... به طور سنتی، کامپوننت فرم چک باکس (checkbox) برای دریافت این نوع ورودی‌ها استفاده می‌شود. گرچه، در طراحی‌های رابط مدرن، دکمه‌‌های toggle معمولا به جای جایگزین چک باکس‌ها استفاده می‌شوند؛ حتی با این وجود که برخی نگرانی‌های دسترسی پذیری وجود دارند.

در این آموزش، نحوه ساخت یک کامپوننت دکمه toggle سفارشی با استفاده از React را خواهیم دید. در انتهای آموزش، ما یک برنامه React ساخته خواهیم بود که از کامپوننت دکمه toggle ما استفاده می‌کند.

در اینجا دمویی از برنامه نهایی که در این آموزش خواهیم ساخت را مشاهده می‌نمایید:

  1. پیش نیازها
  2. شروع کار
  3. کامپوننت ToggleSwitch
  4. استایل‌بندی ToggleSwitch
  5. ساخت برنامه نمونه
  6. نگرانی‌های دسترسی پذیری
  7. نتیجه گیری

پیش نیازها

قبل از شروع کار، باید مطمئن شوید که Node را بر روی سیستم خود نصب دارید. همچنین پیشنهاد می‌کنم که ابزار مدیریت پکیج Yarn را بر روی دستگاه خود نصب کنید؛ زیرا ما از آن به جای npm‌ که به همراه Node وجود دارد استفاده خواهیم کرد.

ما کد boilerplate را برای برنامه React خود با استفاده از پکیج خط دستوری create-react-app خواهیم ساخت. همچنین شما باید مطمئن شوید که این پکیج به صورت global بر روی سیستم شما نصب می‌شود. اگر از npm نسخه ۵.۲ و بالاتر استفاده می‌کنید، شاید نیاز نباشد که create-react-app را به عنوان یک dependency نوع global نصب کنید؛ زیرا ما می‌توانیم از دستور npx استفاده کنیم.

در آخر، این آموزش فرض می‌کند که شما از پیش با React آشنا هستید. اگر نه، می‌توانید آموزش‌های راکت را حول محور React دنبال کنید.

شروع کار

یک برنامه جدید بسازید

با استفاده از دستور زیر، یک برنامه React جدید را شروع کنید. شما می‌توانید برنامه را به هر نحوی که ترجیح می‌دهید، نامگذاری کنید.

create-react-app react-toggle-switch

npm نسخه ۵.۲ و بالاتر:

npx create-react-app react-toggle-switch

Dependencyها را نصب کنید

سپس ما dependencyهای مورد نیاز برای برنامه خود را نصب می‌کنیم. این دستور را اجرا کنید، تا dependencyهای مورد نیاز را نصب کنید:

yarn add lodash bootstrap prop-types classnames

yarn add -D npm-run-all node-sass-chokidar

ما node-sass-chokidar را به عنوان dependency توسعه برای برنامه خود نصب کرده‌ایم تا استفاده از SASS را ممکن کنیم.

اسکریپت‌های npm را تغییر دهید

فایل package.json را ویرایش کنید و بخش scripts را به این صورت تغییر دهید:

"scripts": {

  "start:js": "react-scripts start",

  "build:js": "react-scripts build",

  "start": "npm-run-all -p watch:css start:js",

  "build": "npm-run-all build:css build:js",

  "test": "react-scripts test --env=jsdom",

  "eject": "react-scripts eject",

  "build:css": "node-sass-chokidar --include-path ./src --include-path ./node_modules src/ -o src/",

  "watch:css": "npm run build:css && node-sass-chokidar --include-path ./src --include-path ./node_modules src/ -o src/ --watch --recursive"

}

Bootstrap CSS را include کنید

ما پکیج bootstrap را به عنوان یک dependency برای برنامه خود نصب کردیم؛ زیرا ما به برخی استایل‌بندی‌های پیش فرض نیاز خواهیم داشت. برای include کردن bootstrap در برنامه خود، فایل src/index.js را ویرایش کنید و این خط را قبل از بیانیه import اضافه کنید:

import "bootstrap/dist/css/bootstrap.min.css";

برنامه را شروع کنید

با اجرای دستور زیر با استفاده yarn، برنامه را اجرا کنید:

yarn start

حال برنامه شروع شده است و روند توسعه‌دهی می‌تواند شروع شود. دقت کنید که یک تب مرورگر برای شما به همراه عملکرد بارگذاری زنده (live reloading) باز شده است تا همینطور که برنامه را توسعه می‌دهید، با تغییرات اعمال شده همگام باشید.

تا به اینجا، ظاهر برنامه باید به مانند این اسکرین شات باشد:

کامپوننت ToggleSwitch

شاخه جدیدی به نام components داخل شاخه src پروژه خود بسازید. سپس، یک شاخه دیگر به نام ToggleSwitch‌داخل شاخه components بسازید. سپس، دو فایل داخل شاخه src/components/ToggleSwitch با نام‌های index.js و index.css بسازید.

این محتویات را به فایل src/components/ToggleSwitch/index.js اضافه کنید:

/_ src/components/ToggleSwitch/index.js _/

import PropTypes from 'prop-types';

import classnames from 'classnames';

import isString from 'lodash/isString';

import React, { Component } from 'react';

import isBoolean from 'lodash/isBoolean';

import isFunction from 'lodash/isFunction';

import './index.css';

class ToggleSwitch extends Component {}

ToggleSwitch.propTypes = {

  theme: PropTypes.string,

  enabled: PropTypes.oneOfType([

    PropTypes.bool,

    PropTypes.func

  ]),

  onStateChanged: PropTypes.func

}

export default ToggleSwitch;

در این قطعه کد، ما کامپوننت ToggleSwitch را ساختیم و typecheckهایی برای ویژگی‌هایش اضافه کردیم.

  • theme - یک رشته، نمایانگر استایل و رنگی که برای دکمه toggle استفاد خواهد شد می‌باشد.
  • enabled - یا می‌تواند یک Boolean باشد، یا یک تابع که یک Boolean را بر می‌گرداند، و state دکمه toggle را وقتی که رندر شده است، تعیین می‌کند.
  • onStateChanged - یک تابع callback می‌باشد که وقتی که state دکمه toggle تغییر می‌کند، فراخوانی می‌شود. این برای فعال کردن actionهایی بر روی کامپوننت والد، وقتی که دکمه روشن است،‌ کاربردی می‌باشد.

راه‌اندازی state مربوط به ToggleSwitch

در قطعه کد زیر، ما state مربوط به کامپوننت ToggleSwitch را راه‌اندازی می‌کنیم و برخی متدهای کامپوننت را برای دریافت state مربوط به دکمه Toggle تعریف می‌کنیم.

/_ src/components/ToggleSwitch/index.js _/

class ToggleSwitch extends Component {

  state = { enabled: this.enabledFromProps() }

  isEnabled = () => this.state.enabled

  enabledFromProps() {

    let { enabled } = this.props;

    // اگر یک تابع فعال است، آن را فراخوانی کن.

    enabled = isFunction(enabled) ? enabled() : enabled;

    // Return enabled if it is a boolean, otherwise false

    return isBoolean(enabled) && enabled;

  }

}

در اینجا، متد enabledFromProps() ویژگی enabled که ما منتقل کردیم را مقرر می‌کند و یک boolean‌ را بر می‌گرداند، که نمایانگر این است که آیا دکمه وقتی که رندر می‌شود باید فعال باشد یا نه. اگر ویژگی enabled یک boolean‌ باشد، مقدار Boolean را بر می‌گرداند. اگر یک تابع باشد، اول قبل از این که تعیین کند مقدار برگشتی یک Boolean است، آن تابع را فراخوانی می‌کند. در غیر این صورت، مقدار false را بر می‌گرداند.

Toggle کردن ToggleSwitch

بیایید ادامه دهیم و متدی که وقتی بر روی دکمه کلیک می‌شود آن را روشن می‌کند را تعریف کنیم.

/_ src/components/ToggleSwitch/index.js _/

class ToggleSwitch extends Component {

  // باقی اعضای کلاس در اینجا...

  toggleSwitch = evt => {

    evt.persist();

    evt.preventDefault();

    const { onClick, onStateChanged } = this.props;

    this.setState({ enabled: !this.state.enabled }, () => {

      const state = this.state;

      // Augument the event object with SWITCH_STATE

      const switchEvent = Object.assign(evt, { SWITCH_STATE: state });

      // اجرای توابع

      isFunction(onClick) && onClick(switchEvent);

      isFunction(onStateChanged) && onStateChanged(state);

    });

  }

}

از آنجایی که متد به عنوان یک event listener از نوع click فعال خواهد شد، ما آن را با پارامتر evt اعلام کرده‌ایم. در ابتدا، این متد وضعیت enabled فعلی را با استفاده از عملکر منطقی NOT (!) فعال می‌کند. وقتی که state بروزرسانی شده است، تابع callback‌ منتقل شده به ویژگی‌های onClick و onStateChanged را فعال می‌کند.

دقت کنید از آنجایی که onClick نیازمند یک رویداد به عنوان اولین آرگومان خود است، ما یک ویژگی SWITCH_STATE اضافی، شامل آبجکت state جدید را به رویداد مورد نظر اضافه کردیم. گرچه، تابع onStateChanged به همراه آبجکت state جدید فراخوانی می‌شود.

رندر کردن ToggleSwitch

در آخر، بیایید متد render() را برای کامپوننت ToggleSwitch پیاده‌سازی کنیم.

/_ src/components/ToggleSwitch/index.js _/

class ToggleSwitch extends Component {

  // باقی اعضای کلاس در اینجا...

  render() {

    const { enabled } = this.state;

    // ویژگی‌های خاص را جدا کن و باقی آن‌ها را ذخیره کن

    const { enabled: _enabled, theme, onClick, className, onStateChanged, ...restProps } = this.props;

    // اگر تم معتبر منتقل نشده است، از تم پیشفرض استفاده کن

    const switchTheme = (theme && isString(theme)) ? theme : 'default';

    const switchClasses = classnames(

      `switch switch--${switchTheme}`,

      className

    )

    const togglerClasses = classnames(

      'switch-toggle',

      `switch-toggle--${enabled ? 'on' : 'off'}`

    )

    return (

      <div className={switchClasses} onClick={this.toggleSwitch} {...restProps}>

        <div className={togglerClasses}></div>

      </div>

    )

  }

}

اتفاقات زیادی در این متد render() در حال گذر است، پس بیایید آن را بشکافیم.

۱. در ابتدا، وضعیت enabled از state کامپوننت تخریب شده است.

۲. سپس، ما ویژگی‌های کامپوننت را تخریب می‌کنیم و restProps که به دکمه منتقل خواهد شد را استخراج می‌کنیم. این کار ما را قادر می‌سازد تا ویژگی‌های خاص کامپوننت را جداسازی کنیم.

۳. سپس، ما از نام‌های کلاس استفاده می‌کنیم تا کلاس‌ها را برای دکمه، بر پایه stateهای theme و enabled کامپوننت بسازیم.

۴. در آخر، ما عناصر DOM را با ویژگی‌ها و کلاس‌های مناسب رندر می‌کنیم. دقت کنید که ما this.toggleSwitch را به عنوان event listener‌ نوع click بر روی دکمه منتقل کردیم.

استایل‌بندی ToggleSwitch

حال که کامپوننت ToggleSwitch خود و عملکردهای مورد نیاز آن را داریم، ادامه می‌دهیم و استایل‌های مورد نظر برای دکمه Toggle را می‌نویسیم.

این قطعه کد را به فایل src/components/ToggleSwitch/index.scss که پیش‌تر ساختید، اضافه کنید:

/_ src/components/ToggleSwitch/index.scss _/

// متغیرهای رنگ پیشفرض

$ball-color: #ffffff;

$active-color: #62c28e;

$inactive-color: #cccccc;

// متغیرهای سایز پیشفرض

$switch-size: 32px;

$ball-spacing: 2px;

$stretch-factor: 1.625;

// متغیرهای کلاس پیشفرض

$switch-class: 'switch-toggle';

/_ SWITCH MIXIN _/

@mixin switch($size: $switch-size, $spacing: $ball-spacing, $stretch: $stretch-factor, $color: $active-color, $class: $switch-class) {}

در اینجا، ما برخی متغیرهای پیشفرض را تعریف کردیم و یک mixin (مخلوط) switch ساختیم. در بخش بعدی، ما این مخلوط را پیاده‌سازی خواهیم کرد؛ اما اول بیایید پارامترهای مخلوط switch را بررسی کنیم:

  • $size - ارتفاع عنصر دکمه. این مقدار باید یک واحد طول داشته باشد. به طور پیشفرض، مقدار آن 32px است.
  • $spacing - فاصله بین توپ دایره‌ای و محفظه دکمه. این مقدار باید یک واحد طول داشته باشد. به طور پیشفرض، مقدار آن 2px است.
  • $stretch - فاکتوری که برای تعیین محدوده عرض کش آمدن عنصر دکمه استفاده می‌شود. این مقدار باید یک عدد بدون واحد باشد. به طور پیشفرض، برابر با 1.625 است.
  • $color - رنگ دکمه، وقتی که فعال است. این مقدار، باید یک مقدار رنگ معتبر باشد. دقت کنید که رنگ توپ دایره‌ای، بدون توجه به این رنگ همیشه سفید است.
  • $class - کلاس پایه برای تشخیص دکمه. این مورد برای این استفاده می‌شود که به طور دینامیک کلاس‌های state دکمه را بسازیم. به طور پیشفرض، مقدار آن «switch-toggle» است. از این رو، کلاس‌های state پیشفرض، .switch-toggle--on و .switch-toggle--off هستند.

پیاده سازی مخلوط دکمه

پیاده‌سازی این مخلوط را در اینجا مشاهده می‌نمایید:

/_ src/components/ToggleSwitch/index.scss _/

@mixin switch($size: $switch-size, $spacing: $ball-spacing, $stretch: $stretch-factor, $color: $active-color, $class: $switch-class) {

  // متغیرهای انتخاب کننده

  $self: '.' + $class;

  $on: #{$self}--on;

  $off: #{$self}--off;

  // متغیرهای دکمه

  $active-color: $color;

  $switch-size: $size;

  $ball-spacing: $spacing;

  $stretch-factor: $stretch;

  $ball-size: $switch-size - ($ball-spacing _ 2);

  $ball-slide-size: ($switch-size _ ($stretch-factor - 1) + $ball-spacing);

  // استایل‌های دکمه

  height: $switch-size;

  width: $switch-size * $stretch-factor;

  cursor: pointer !important;

  user-select: none !important;

  position: relative !important;

  display: inline-block;

  &#{$on},

  &#{$off} {

    &::before,

    &::after {

      content: '';

      left: 0;

      position: absolute !important;

    }

    &::before {

      height: inherit;

      width: inherit;

      border-radius: $switch-size / 2;

      will-change: background;

      transition: background .4s .3s ease-out;

    }

    &::after {

      top: $ball-spacing;

      height: $ball-size;

      width: $ball-size;

      border-radius: $ball-size / 2;

      background: $ball-color !important;

      will-change: transform;

      transition: transform .4s ease-out;

    }

  }

  &#{$on} {

    &::before {

      background: $active-color !important;

    }

    &::after {

      transform: translateX($ball-slide-size);

    }

  }

  &#{$off} {

    &::before {

      background: $inactive-color !important;

    }

    &::after {

      transform: translateX($ball-spacing);

    }

  }

}

در این مخلوط، ما با تعیین برخی متغیرها بر پایه پارامترهای منتقل شده به مخلوط شروع می‌کنیم. سپس ادامه داده، و استایل‌ها را می‌سازیم. دقت کنید که ما از شبه عنصرهای ::after و ::before برای ساخت دینامیک کامپوننت دکمه استفاده می‌کنیم. ::before محفظه دکمه را می‌سازد و ::after توپ دایره‌ای را می‌سازد.

همچنین به نحوه ساخت کلاس‌های state از کلاس پایه و اختصاص‌دهی آن‌ها به متغیرها دقت کنید. متغیر $on مربوط به انتخاب کننده state فعال شده map می‌شود، و متغیر $off به انتخاب کننده state غیر فعال map می‌شود.

ما همچنین تضمین کردیم که کلاس پایه (.switch-toggle) باید به همراه یک کلاس state (.switch-toggle--on و .switch-toggle--off) برای استایل‌های در دسترس ساخته شود. از این رو، ما از انتخاب کننده‌های &#{$on} و &#{$off} استفاده کردیم.

ساخت دکمه‌های تم‌بندی شده

حال که ما مخلوط switch خود را داریم، ادامه می‌دهیم و برخی استایل‌های تم‌بندی شده را برای دکمه toggle می‌سازیم. ما دو تم می‌سازیم: default و graphite-small.

این قطعه کد را به فایل src/components/ToggleSwitch/index.scss اضافه کنید:

/_ src/components/ToggleSwitch/index.scss _/

@function get-switch-class($selector) {

  // First parse the selector using `selector-parse`

  // Extract the first selector in the first list using `nth` twice

  // Extract the first simple selector using `simple-selectors` and `nth`

  // Extract the class name using `str-slice`

  @return str-slice(nth(simple-selectors(nth(nth(selector-parse($selector), 1), 1)), 1), 2);

}

.switch {

  $self: &;

  $toggle: #{$self}-toggle;

  $class: get-switch-class($toggle);

  // default theme

  &#{$self}--default > #{$toggle} {

    // Always pass the $class to the mixin

    @include switch($class: $class);

  }

  // graphite-small theme

  &#{$self}--graphite-small > #{$toggle} {

    // A smaller switch with a `gray` active color

    // Always pass the $class to the mixin

    @include switch($color: gray, $size: 20px, $class: $class);

  }

}

در اینجا ما اول یک تابع Sass به نام get-switch-class می‌سازیم که یک $selector را به عنوان پارامتر می‌گیرد. این تابع $selector را از طریق زنجیره‌ای از توابع Sass اجرا می‌کند و تلاش می‌کند که اولین نام کلاس را استخراج کند. برای مثال اگر این موارد را دریافت کند:

  • .class-1 .class-2 .class-3 .class-4، مقدار class-1 را بر می‌گرداند.
  • .class-5 .class-6 .class-7 .class-7، مقدار class-5 را بر می‌گرداند.

سپس، ما استایل‌ها را براس کلاس .switch‌ تعریف می‌کنیم. ما به طور دینامیک کلاس toggle را برابر با .switch-toggle قرار می‌دهیم و آن را به متغیر $toggle اختصاص می‌دهیم. دقت کنید که ما نام کلاس برگردانده شده از فراخوانی تابع get-switch-class() را به متغیر $class اختصاص می‌دهیم. در آخر، ما مخلوط switch را با پارامترهای ضروری پر می‌کنید تا کلاس‌های تم را بسازیم.

دقت کنید که ساختار انتخاب کننده دکمه تم‌بندی شده چنین حالتی دارد: &#{$self}--default > #{$toggle} (در صورت استفاده از تم پیشفرض به عنوان یک مثال). به طور خلاصه، این یعنی سلسله مراتب عناصر باید چنین ظاهری داشته باشد تا استایل‌ها اعمال شوند:

<!-- Use the default theme: switch--default  -->

<element class="switch switch--default">

  <!-- The switch is in enabled state: switch-toggle--on -->

  <element class="switch-toggle switch-toggle--on"></element>

</element>

در اینجا دمویی از ظاهر تم‌های دکمه را مشاهده می‌نمایید:

ساخت برنامه نمونه

حال که ما کامپوننت ToggleSwitch را به همراه استایل‌های مورد نیاز داریم، بیایید ادامه دهیم و شروع به ساخت برنامه نمونه کنیم که در بخش ابتدایی آن را دیدیم.

فایل src/App.js را ویرایش کنید تا چنین ظاهری داشته باشد:

/_ src/App.js _/

import classnames from 'classnames';

import snakeCase from 'lodash/snakeCase';

import React, { Component } from 'react';

import Switch from './components/ToggleSwitch';

import './App.css';

// لیست فعالیت‌هایی که می‌توانند اعلانات را فعال کنند

const ACTIVITIES = [

  'News Feeds', 'Likes and Comments', 'Live Stream', 'Upcoming Events',

  'Friend Requests', 'Nearby Friends', 'Birthdays', 'Account Sign-In'

];

class App extends Component {

  // راه‌اندازی وضعیت برنامه، تمام فعالیت‌ها به طور پیشفرض فعال هستند

  state = { enabled: false, only: ACTIVITIES.map(snakeCase) }

  toggleNotifications = ({ enabled }) => {

    const { only } = this.state;

    this.setState({ enabled, only: enabled ? only : ACTIVITIES.map(snakeCase) });

  }

  render() {

    const { enabled } = this.state;

    const headingClasses = classnames(

      'font-weight-light h2 mb-0 pl-4',

      enabled ? 'text-dark' : 'text-secondary'

    );

    return (

      <div className="App position-absolute text-left d-flex justify-content-center align-items-start pt-5 h-100 w-100">

        <div className="d-flex flex-wrap mt-5" style={{width: 600}}>

          <div className="d-flex p-4 border rounded align-items-center w-100">

            <Switch theme="default"

              className="d-flex"

              enabled={enabled}

              onStateChanged={this.toggleNotifications}

            />

            <span className={headingClasses}>Notifications</span>

          </div>

          {/_ ...Notification options here... _/}

        </div>

      </div>

    );

  }

}

export default App;

در اینجا ما یک constant با نام ACTVITIES را به همراه آرایه‌ای از فعالیت‌هایی که می‌توانند اعلانات را فعال کنند، راه‌اندازی می‌کنیم. سپس، ما state برنامه را با دو ویژگی راه‌اندازی می‌کنیم:

  • enabled - یک Boolean که نشان می‌دهد آیا اعلانات فعال شده‌اند، یا نه.
  • only - یک آرایه که شامل تمام فعالیت‌هایی که می‌توانند اعلانات را فعال کنند می‌باشد.

دقت کنید که ما از ابزار snakeCase از Lodash‌ استفاده کردیم تا تمام فعالیت‌ها را قبل از بروزرسانی state، تبدیل به snakecase کنیم. از این رو، «News Feeds» تبدیل به «news_feeds» می‌شود.

سپس، ما متد toggleNotifications() را فعال کردیم که state برنامه را بر پایه stateای که از دکمه اعلانات دریافت می‌کند، بروزرسانی می‌کند. این به عنوان تابع callback منتقل شده به ویژگی onStateChanged دکمه استفاده می‌شود. دقت کنید وقتی که برنامه فعال است، تمام فعالیت‌ها به طور پیشفرض فعال خواهند بود؛ زیرا ویژگی only با تمام فعالیت‌ها پر شده است.

در آخر، ما عناصر DOM را برای برنامه رندر کردیم و یک اسلات برای گزینه‌های اعلانات که به زودی اضافه خواهند شد، رها کردیم. تا به اینجا، برنامه ما باید چنین ظاهری داشته باشد:

سپس ادامه دهید و به دنبال خطی بگردید که این کامنت را دارد:

{/_ ...Notification options here... _/}

و آن را با این محتویات جایگزین کنید تا گزینه‌های اعلانات را رندر کنید:

{ enabled && (

  <div className="w-100 mt-5">

    <div className="container-fluid px-0">

      <div className="pt-5">

        <div className="d-flex justify-content-between align-items-center">

          <span className="d-block font-weight-bold text-secondary small">Email Address</span>

          <span className="text-secondary small mb-1 d-block">

            <small>Provide a valid email address with which to receive notifications.</small>

          </span>

        </div>

        <div className="mt-2">

          <input type="text" placeholder="mail@domain.com" className="form-control" style={{ fontSize: 14 }} />

        </div>

      </div>

      <div className="pt-5 mt-4">

        <div className="d-flex justify-content-between align-items-center border-bottom pb-2">

          <span className="d-block font-weight-bold text-secondary small">Filter Notifications</span>

          <span className="text-secondary small mb-1 d-block">

            <small>Select the account activities for which to receive notifications.</small>

          </span>

        </div>

        <div className="mt-5">

          <div className="row flex-column align-content-start" style={{ maxHeight: 180 }}>

            { this.renderNotifiableActivities() }

          </div>

        </div>

      </div>

    </div>

  </div>

) }

دقت کنید که ما یک درخواست به this.renderNotificationActivities() ارسال کردیم تا فعالیت‌ها را رندر کند. بیایید ادامه دهیم و این متد و دیگر متدهای باقی را رندر کنیم.

این متدها را به کامپوننت App اضافه کنید:

/_ src/App.js _/

class App extends Component {

  toggleActivityEnabled = activity => ({ enabled }) => {

    let { only } = this.state;

    if (enabled && !only.includes(activity)) {

      only.push(activity);

      return this.setState({ only });

    }

    if (!enabled && only.includes(activity)) {

      only = only.filter(item => item !== activity);

      return this.setState({ only });

    }

  }

  renderNotifiableActivities() {

    const { only } = this.state;

    return ACTIVITIES.map((activity, index) => {

      const key = snakeCase(activity);

      const enabled = only.includes(key);

      const activityClasses = classnames(

        'small mb-0 pl-3',

        enabled ? 'text-dark' : 'text-secondary'

      );

      return (

        <div key={index} className="col-5 d-flex mb-3">

          <Switch theme="graphite-small"

            className="d-flex"

            enabled={enabled}

            onStateChanged={ this.toggleActivityEnabled(key) }

          />

          <span className={activityClasses}>{ activity }</span>

        </div>

      );

    })

  }

}

در اینجا، ما متد renderNotifcationActivities را پیاده‌سازی کرده‌ایم. ما با استفاده از ACTIVITIES.map()، در طی تمام فعالیت‌ها تکرار (iterate) می‌کنیم و هر مورد را به همراه یک دکمه toggle برای آن رندر می‌کنیم. دقت کنید که دکمه toggle از تم graphite-small استفاده می‌کند. ما همچنین وضعیت enabled هر فعالیت را با بررسی این که آیا از قبل از متغیر only وجود دارد یا نه، تشخیص می‌دهیم.

در آخر، ما متد toggleActivityEnabled را تعریف کردیم، که از آن استفاده شده بود تا تابع callback مربوط به ویژگی onStateChange دکمه toggle هر فعالیت فراهم شود. ما یک تابع سطح بالا برای آن تعریف کردیم تا بتوانیم فعالیت را به عنوان یک آرگومان منتقل کنیم و تابع callback را برگردانیم. این تابع بررسی می‌کند تا ببیند که آیا فعالیت مورد نظر از پیش فعال شده است یا نه و state را بر حسب آن بروزرسانی می‌کند.

حال برنامه باید به مانند این اسکرین‌شات باشد:

اگر ترجیح می‌دهید که تمام فعالیت‌ها را به مانند آنچه در اسکرین‌شات اولیه نشان داده شده است، به طور پیشفرض به جای فعال، غیرفعال داشته باشید، می‌توانید این تغییرات را به کامپوننت App اعمال کنید:

/_ src/App.js _/

class App extends Component {

  // راه‌اندازی وضعیت برنامه، تمام فعالیت‌ها به طور پیشفرض فعال هستند

  state = { enabled: false, only: [] }

  toggleNotifications = ({ enabled }) => {

    const { only } = this.state;

    this.setState({ enabled, only: enabled ? only : [] });

  }

}

نگرانی‌های دسترسی پذیری

استفاده از دکمه toggle در برنامه‌های خود به جای چک باکس‌های سنتی، می‌تواند رابط‌های مرتب‌تری را برای ما فراهم کند. به خصوص با در نظر گرفتن این حقیقت که استایل‌بندی چک باکس‌های سنتی به گونه‌ای که می‌خواهیم، سخت است.

گرچه، استفاده از دکمه‌های toggle به جای چک باکس‌ها، برخی مشکلات دسترسی‌پذیری را نیز دارد؛ زیرا عامل کاربر ممکن است نتواند تابع کامپوننت را به درستی تفسیر کند.

چند کار می‌توانند انجام شوند تا دسترسی‌پذیری دکمه toggle ارتقا داده شود و عوامل کاربری را قادر سازند تا به درستی این نقش را درک کنند. برای مثال، می‌توانید از این صفات ARIA استفاده کنید:

<switch-element tabindex="0" role="switch" aria-checked="true" aria-labelledby="#label-element"></switch-element>

 شما همچنین می‌توانید منتظر رویدادهای بیشتری بر روی دکمه toggle باشید تا راه‌های بیشتری بسازید که کاربر بتواند با کامپوننت در ارتباط باشد.

نتیجه گیری

در این‌ آموزش، ما توانستیم دکمه toggle سفارشی را برای برنامه‌های React خود با استایل‌بندی‌های مناسب که تم‌های مختلفی را پشتیبانی می‌کنند، بسازیم. ما همچنین توانسته‌ایم از آن در برنامه خود به جای چک باکس‌هاس سنتی استفاده کنیم.

برای سورس کد کامل این آموزش،‌ مخزن react-toggle-switch-demo را بر روی گیت‌هاب مشاهده کنید. شما همچنین می‌توانید دموی زنده این آموزش را بر روی Sandbox ببینید.

منبع

مقالات پیشنهادی

آیکون های زیبا و کاربردی طراحی وب | سری دوم

آیکون ها امروزه نقش کلیدی در طراحی وب دارند بطوری که حتی برای نشون دادن اطلاعات ازشون استفاده میشه . این آیکون ها چیزی از بوجود اومدنشون نمیگذره و بوس...

با استفاده از React، صفحه‌ بندی‌ سفارشی‌سازی شده بسازید

اکثر مواقع، در موقعیتی قرار می‌گیریم که باید یک وب‌اپلیکیشن بسازیم که نیاز است حجم زیادی داده را از یک سرور کنترل از راه دور، یک API یا یک دیتابیس دری...

آیکون های زیبا و کاربردی طراحی وب | سری سوم

آیکون ها امروزه نقش کلیدی در طراحی وب دارند بطوری که حتی برای نشون دادن اطلاعات ازشون استفاده میشه . این آیکون ها چیزی از بوجود اومدنشون نمیگذره و بوس...

آیکون های فروشگاهی و بازاریابی

در این پست لذت بخش من میخوام به شما یک مجموعه از آیکون های زیبا و ضررویه بازاریابی و فروشگاهی رو معرفی کنم که شامل +100 آیکون Swificons با 3 نوع مختلف...