1 of 45

Лекція 4

Keys, Ref, Forms

2 of 45

1. Повторення методу map JavaScript

Метод map

ім'я_масиву . map ( функція)

  • map повертає новий масив
  • Елементами цього масиву будуть значення, отримані після впливу функції-параметра на кожне значення оригінального масиву.
  • Оригінальний масив у результаті виклику map не змінюється

Приклад кожного елемента масиву буде викликана функція підрахунку квадратного кореня:

.

let arr = [ 9 , 4 , 16 ];

console . Log ( arr );

let mArr = arr. map ( Math . sqrt ); // 3 2 4

console . Log ( mArr );

Під час виклику map для кожного елемента arr була викликана функція підрахунку квадратного кореня. З map повернувся новий масив зі значеннями з arr після підрахунку квадратного кореня. Саме тому в mArr містяться елементи із значеннями 3 2 4.

3 of 45

Синтаксис map для виклику функції користувача :

ім'я_масиву . map ( функція користувача (поточний елемент) {

тіло

})

  • Функцію буде викликано для кожного елемента масиву.
  • Як параметр функція приймає поточний, аналізований елемент масиву. Цей параметр буде заповнено автоматично.

Приклад функція користувача буде зводити в квадрат кожен елемент масиву:

let arr = [ 3 , 4 , 7 ];

console . Log ( arr );

let mArr = arr .map ( function (item) {

return Math .pow (item, 2 );

});

console . Log ( mArr ); // 9 16 49

!!! Користувальницька функція _ має повертати значення.

4 of 45

Приклад із використанням стрілочної функції:

let arr = [ 3 , 4 , 7 ];

console . Log ( arr );

let mArr = arr .map ((item) => {

return Math .pow (item, 2 );

});

console . Log ( mArr ); //9 16 49

let mArr = arr .map (item => Math .pow (item, 2 ));

Приклад із масивом об'єктів. Об'єкт міститиме інформацію про прізвище та вік. Користувацька функція збільшуватиме вік на 10 років:

let users = [{ lastName : "Brown" , age: 30 }, { lastName : " Davids " , age: 40 }];

let mUsers = users .map (item => {

item . age + = 10 ;

return item;

});

Або можна написати так:

5 of 45

Згадаймо про деструктуризацію об'єктів та масивів:

Деструктуризація дозволяє розбивати об'єкт чи масив на змінні під час присвоєння.

  • Повний синтаксис для об'єкта:

let { prop : varName = default , ... rest } = object

Властивості, які були згадані, копіюються в об'єкт rest .

  • Повний синтаксис для масиву:

let [item1 = default , item2, ... rest ] = array

Перший елемент відправляється в item1 ; другий відправляється в item2 , решта всіх елементів потрапляють в масив rest .

Можна витягувати дані з вкладених об'єктів та масивів, для цього ліва сторона повинна мати ту саму структуру, що й права.

6 of 45

2. Використання масивів у React- додатках

Приклад із використанням деструктуризації об'єктів:

let user = { name: "Ann " , lastName : "Green" };

let {... myUser } = user ;

console . log ( myUser );

За допомогою синтаксису деструктуризації {… myUser } створюється новий об'єкт

myUser . В нього буде скопійовано вміст та пристрій об'єкта user . Це означає, що всередині muUser буде два поля: name і lastName . У name буде Ann. LastName буде Green. _

Приклад використання масиву.

Відобразимо елементи масиву у додатку. У коді нижче у нас є масив об'єктів з інформацією про письменників (ім'я та прізвище). Ми показуватимемо цю інформацію на екран. Зовнішній вигляд нашої програми:

7 of 45

Рішення : створимо кілька додаткових функціональних компонентів. Перший компонент Writer міститиме інформацію про одного письменника. Другий компонент WritersList буде показувати список всіх письменників з інформацією про них. Код файлу App.js :

import React from "react" ;

import "./styles.css" ;

let writers = [

{ name: "Tom", lastName: "Hanks" },

{ name: "Meryl", lastName: "Streep" },

{ name: "Leonardo", lastName: "DiCaprio" }

];

// Компонента з інформацією про письменника

function Writer(props) {

return (

<>

<div> { props . name } { props . lastName }</ div >< hr />

</>

);

}

// Список письменників

function WritersList () {

return (

< div >< Writer {...writers[ 0 ]} />

< Writer {...writers[ 1 ]} />

< Writer {...writers[ 2 ]} />

</ div >

);

}

export default function App() {

return (

<>

< WritersList />

</>

);

}

Масив writers оголошено на глобальному рівні у нашому коді.

Компонент Writer відповідає за відображення даних письменника . Інформація про письменника буде передана всередину компоненти через props .

Компонента WritersList відображатиме масив письменників. Це означає, що всередині коду ми будемо створювати об'єкт конкретного письменника (об'єкт компоненти Writer )

Конструкція виду:

<Writer {...writers[0]} />

Ми створюємо об'єкт Writer . Як його props ми передаємо йому об'єкт writers [0] . Для цього використано синтаксис деструктуризації. Всередину props буде скопійовано повністю вміст writers [0]. Це означає, що всередині props буде створено властивості name і lastName .

Значення в них буде скопійовано з відповідних полів writers[0] .

У нашому масиві три елементи, тому ми повторюємо створення компоненти Writer тричі у коді з різними індексами (0,1,2).

8 of 45

Кожен елемент масиву ми вказуємо явно WritersList . У коді ми робили це три рази. Це незручно та не масштабовано. Виправимо App.js :

import React from "react" ;

import "./styles.css" ;

let writers = [

{ name: "Tom", lastName: "Hanks" },

{ name: "Meryl", lastName: "Streep" },

{ name: "Leonardo", lastName: "DiCaprio" }

];

function Writer (props) {

return (

<>

<div> { props . name } { props . lastName } </ div >< hr />

</>

);

}

function WritersList (props) {

return (

<div> { props . data . map (item => ( < Writer {...item} /> )) } </ div >

);

}export default function App () {

return (

<>

< WritersList data = { writers } />

</>

);

}

Ми передаємо масив writers через властивість data

всередину компоненти WritersList

Викликаємо метод map для властивості data (посилається на масив writers )

item => <Writer {...item} />

Для кожного елемента масиву writers викликається цей код. У цьому коді повертається елемент для нового масиву. Фактично ми створюємо новий елемент Writer і заповнюємо його props значеннями властивостей поточного, аналізованого елемента . На місце виклику map буде вставлено новий, створений масив об'єктів типу Writer

9 of 45

3. Ключ

В онлайн-редакторі CodeSandbox є блок інтерфейсу, який відображає консоль. Якщо відкрити наш приклад із масивом в нижньому правому кутку можна побачити щось подібне :

React попереджає нас, що кожен елемент у списку повинен бути свій унікальний ключ . Ми ставили з начення для елемент. Значення для ключів ми не ставили.

10 of 45

  • Ключ - це деяке унікальне значення, яке не змінюватиметься.
  • React використовує ключі, щоб розуміти, які елементи були додані, видалені, змінено.
  • Щоб бути впевненими у правильному оновленні інтерфейсу, потрібно обов'язково ставити ключі.
  • Унікальність ключів має підтримуватись у рамках одного списку. Це означає, що ключі у різних списках можуть бути не унікальними.
  • Для завдання ключа використовується атрибут key .

Приклад роботи з до лючами . У нашому прикладі буде масив міст, яке ми будемо відображати. Кожен елемент списку міст буде задано свій унікальний ключ

11 of 45

import React from "react" ;

import "./styles.css" ;

const cities = [ " Dubai" , " Rome" , " Beijing" ];

function City(props) {

return < div > { props . value } </div> ;

}

function CityList (props) {

const citiesData = props . data .map (city => < City key = {city} value = {city} />);

return <>{ citiesData }</>;

}

export default function App() {

return (

<> < CityList data = { cities } /> </>

);

}

Код App.js :

Функція-параметр для map виглядає трохи інакше. Ми говоримо, що елемент списку міст має дві властивості. Перша властивість value – назва міста. Друга властивість key — ключ для поточного рядка, що створюється. Ключ не відображається в інтерфейсі. Користувач не бачить. Цей ключ потрібний для React . У цьому прикладі ми як ключ використовували назву міста.

Якщо назва міста в масиві зустрічатиметься більше одного разу, тоді наш підхід перестане працювати.

Для того, щоб уникнути потенційних проблем, як ключ використовують ідентифікатори.

Ми передали масив через властивість data

12 of 45

Дуже важливо запам'ятати, що ключ треба передавати там, де створюється список міст, а не всередині компонента City .

Код нижче не є вірним для завдання ключа:

function City(props) {

return < div key = { props . value }>{ props . value } </div> ;

}

function CityList (props) {

const citiesData = props . data .map (city => < City value = {city} />);

return <>{ citiesData }</>;

}

Ми поставили атрибут key всередині компоненти City в div тегу . Такий підхід не дозволяє React ідентифікувати

рядки списку.

Змінимо код прикладу з письменниками. Впровадимо підтримку ключів. Як ключ ми будемо використовувати унікальні ідентифікатори. Для цього ми додамо

властивість id всередину об'єкта письменника

13 of 45

import React from "react" ;

import "./styles.css" ;

let writers = [

{ id: 1, name: "Harper", lastName: "Lee" },

{ id: 2, name: "George", lastName: "Orwell" },

{ id: 3, name: "J.R.R.", lastName: "Tolkien" }

];

function Writer(props) {

return (

<> <div> { props . name } { props . lastName }</ div >< hr /></>

);

}

function WritersList (props) {

return (

<div>

{ props . data .map (item => (

< Writer key = { item . id } {...item} />

))}

</ div >

);

}

export default function App() {

return (

<>< WritersList data ={ writers } /></>

);

}

ми явно вказуємо атрибут key і задаємо йому значення item.id

В результаті використання key попередження зникло, але саме головне, що тепер React точно відрізняє один рядок списку письменників від іншої

14 of 45

Передача даних з компонентів до компонентів

У React дані передаються від батьківського компонента до дочірнього через пропси ( props ).

Якщо потрібно передати дані з дочірнього компонента до батьківського , можна визначити функцію зворотного дзвінка ( callback function ) у батьківському компоненті та передати її до дочірнього компонента через пропси .

У дочірньому компоненті можна викликати цю функцію зворотного виклику та передати їй дані як аргументи. Ці дані потім будуть передані батьківському компоненту і можуть бути використані там для оновлення стану або виконання інших дій.

Наприклад , припустимо, є батьківський компонент Parent і дочірній компонент Child . У Parent визначимо функцію зворотного виклику handleData , яка прийматиме дані з Child як аргумент:

function Parent () {

function handleData (data) {

console . log ( 'Received data:' , data); /

}

return (<div><Child onData = { handleData } /></div>);

}

15 of 45

У Child ви можете викликати функцію onData , передавши їй дані як аргумент:

function Child (props) {

function handleClick () {

const data = 'Some data' ;

props. onData (data);

}

return (<button onClick = { handleClick } >Send data to parent</button>);

}

Коли користувач натисне кнопку в Child , буде викликана функція handleClick , яка передасть дані батьківський компонент через функцію зворотного виклику onData . У батьківському компоненті дані будуть виведені в консоль, і виконати додаткові дії з ними.

16 of 45

Завдання 1.

Створіть програму для відображення інформації про міста вашої країни. Обов'язково потрібно використовувати масиви об'єктів, функцію map і функціональні компоненти

Завдання 2.

Створіть програму для відображення інформації про ваші улюблені музичні групи. Обов'язково потрібно використовувати масиви об'єктів, функцію map та класові компоненти

Завдання 3.

Створіть програму для відображення інформації про студентів та їх оцінки з усіх предметів у вашій групі. Також створіть компонент для знаходження середнього балу кожного студента та середнього балу за групою. Обов'язково потрібно використовувати масиви об'єктів, функцію map і функціональні компоненти

17 of 45

5) Розробити програму для відображення списку фільмів. Ваше завдання - відображати список фільмів за допомогою компонента MovieList , який отримуватиме масив фільмів як пропс:

  • Створіть компонент MovieList , який прийматиме масив об'єктів фільмів як пропс.

  • Всередині компонента MovieList створіть стан selectedMovieId , який міститиме ідентифікатор вибраного фільму. Спочатку значення selectedMovieId має дорівнювати null .

  • Створіть функцію handleSelectMovie , яка оновлюватиме стан selectedMovieId при натисканні на елемент списку фільмів. Функція повинна приймати ідентифікатор фільму і встановлювати його в стан selectedMovieId .

  • У компоненті MovieList відобразіть список фільмів за допомогою map . Кожен фільм необхідно відображати як елемент списку (< li >). Для кожного фільму додайте обробник кліка, який буде викликати функцію handleSelectMovie з ідентифікатором вибраного фільму.

  • Використовуючи стан selectedMovieId , відобразіть деталі вибраного фільму в іншому компоненті MovieDetails , який також повинен отримувати масив фільмів як пропс.

  • У компоненті MovieDetails відобразіть деталі вибраного фільму, використовуючи інформацію з масиву фільмів, надісланих через пропси. Якщо selectedMovieId дорівнює null , компонент MovieDetails повинен відображати повідомлення "Виберіть фільм".

18 of 45

6) Розробте програму для відображення списку користувачів. Ваше завдання - відображати список користувачів, використовуючи масив об'єктів користувачів, переданих через props і використовувати map для відображення кожного користувача у вигляді компонента.

  • Створіть компонент UserList , який прийматиме масив об'єктів користувачів як пропс.

  • Всередині компонента UserList створіть стан selectedUser , який міститиме вибраного користувача.

  • Використовуючи хук useState , ініціалізуйте стан selectedUser значенням null .

  • Створіть функцію handleUserClick , яка встановлюватиме вибраного користувача в стан selectedUser .

  • У компоненті UserList відобразіть список користувачів за допомогою map . Кожен користувач повинен відображатися як компонент з ім'ям UserItem . Для кожного користувача передайте props , що містить дані користувача та функцію handleUserClick .

  • Створіть компонент UserItem , який відображатиме дані користувача та додавати обробник події onClick для виклику функції handleUserClick з даними користувача як аргумент. Якщо вибрано цей користувач, необхідно додати клас selected до елемента.

  • При виборі користувача в стан selectedUser необхідно записати об'єкт вибраного користувача.

  • Відобразіть компонент UserList в іншому компоненті.

19 of 45

4. Форми

Розглянемо роботу з формами за допомогою базових механізмів React .

Приклад :

function Form() {

return (

<form>

< input type = "text" />

< input type = "submit" value = "Click me" />

</ form >

);

}

export default function App () {

return (

<>< Form /></>

);

}

Куди відправляються дані у випадку, якщо дія не вказана? Дані форми на сторінці будуть надсилатися самій же сторінці. Наприклад, якщо форма знаходиться у файлі myform.php на сервері, дані після натискання submit будуть надіслані myform.php .

20 of 45

Щоб загальмувати відсилання даних після натискання на кнопку submit , можна використовувати функцію preventDefault . Приклад :

import React from "react" ;

import "./styles.css" ;

function Form() {

const handleSubmit = event => {

// Відмінюємо реакцію оброблювача за замовчуванням:

event .preventDefault ();

// Отримуємо доступ до текстового поля:

let uName = document .getElementById ( " userName " );

alert( uName . value );

};

return (

< form onSubmit ={ handleSubmit }>

< input type = "text" id = " userName " />

< input type = "submit" value = "Click me" />

</ form >

);

}

export default function App() {

return (

<>< Form /></>

);

}

При описі форми вказали, що обробляємо відсилання даних. Подія виникає, коли користувач натискає кнопку submit всередині форми.

У коді нашого обробника ми скасовуємо стандартну обробку події за допомогою виклику preventDefault .

Після чого ми отримуємо доступ до текстового поля та відображаємо його значення

21 of 45

5. Рефи

Рефи - це інструмент для зв'язування елемента форми з деякою змінною. Завдяки такому зв'язуванню можна обмінюватись значеннями з елементом управління. За механізм такої взаємодії відповідає React .

Для створення ref -змінної використовується метод React.createRef () .

Кроки зі створення ref -змінної :

1. Створити ref -змінну за допомогою виклику createRef .

2. Прив'язати її до конкретного елемента керування через атрибут ref .

Після виконання цих кроків наша змінна готова до роботи!

Приклад : Створимо програму з таким інтерфейсом:

Після натискання кнопки ми покажемо вікно повідомлення зі значенням, введеним у текстове поле. Дані на сервер відправлені не будуть, тому що в обробнику onSubmit ми викликаємо preventDefault . У нашому прикладі ми створимо функціональний компонент і ref -змінну:

22 of 45

import React from "react" ;

import "./styles.css" ;

function Form() {

let uRef = React .createRef ();

const handleSubmit = event => {

event .preventDefault ();

alert( uRef . current . value );

};

return (

< form onSubmit ={ handleSubmit }>

< input type = "text" id = " userName " ref ={ uRef } />

< input type = "submit" value = "Click me" />

</ form >

);

}

export default function App() {

return (

<>< Form /></>

);

}

Код App.js :

Створення ref -змінної . Поки що вона не прив'язана до жодного елементу управління

У обробнику onSubmit ми отримуємо доступ до значення елемента управління, з яким пов'язана ref -змінна . Для цього використовується конструкція uRef . current.value

Тут ми пов'язуємо текстове поле та ref -змінну .

Зв'язок відбувається через атрибут ref . Всі питання щодо пересилання даних вирішує React

23 of 45

Приклад роботи з ref -змінними реалізуємо через класові компоненти.

Зовнішній вигляд програми:

Після натискання на кнопку відправлення даних не відбудеться. Ми відобразимо вікно з отриманими від користувача даними. Повний код App.js :

import React , { Component } from "react" ;

import "./styles.css" ;

class Form extends Component {

nameRef = React .createRef ();

lastNameRef = React .createRef ();

render() {

const handlerSubmit = event => {

event .preventDefault ();

let str = this . nameRef . current . value + " ";

str += this . lastNameRef . current . value ;

alert( str );

};

Ми імпортували Component , щоб скоротити запис React.Component до Component при наслідуванні.

Створення та використання ref -змінних працює

також, як у функціональних компонентах

Код обробника onSubmit відрізняється від попередніх прикладів тільки наявністю цього .

24 of 45

return (

< form onSubmit ={ handlerSubmit }>

< div className = " formElement " >

< input type = "text" placeholder = "Input name" ref = { this . nameRef } required />

</ div >

< div className = " formElement " >

< input type = "text" placeholder = "Input last name" ref = { this . lastNameRef } required />

</ div >

< div className = " formElement " >

< input type = "submit" value = "Send data" />

</ div >

</ form >

);

}

}

export default class App extends Component {

render() {

return (

<>< Form /></>

);

}

}

Зв'язування елемента керування також здійснюється через атрибут ref

25 of 45

6. Стан ( State ) та форми

Приклад : якщо ви спробуєте ввести текст у текстове поле, нічого не станеться

import React , { useState } from "react" ;

import "./styles.css" ;

function Form() {

const [ nameState , setNameState ] = useState ( " " );

return (

<form> _ _

< input type = 'text' placeholder = 'Input name' value ={ nameState } required />

< input type = 'submit' value = 'Click me' />

</ form >

);

}

export default function App() {

return (

<>< Form /></>

);

}

У коді ми створюємо змінну стан.

const [ nameState , setNameState ] = useState ( "" );

Для закріплення змінної стану за текстовим полем ми використовуємо властивість value .

<input type = 'text' placeholder = 'Input name' value = { nameState }

Для закріплення ref -змінної ми використовували властивість ref . Чому текст не відображається? Це відбувається через те, що ми закріпили в коді оновлення елемента через React , але не уточнили логіку цього процесу

26 of 45

Логіка процесу оновлення реалізується через обробник onChange для текстового поля.

Тепер змінимо приклад, щоб у текстовому полі з'являвся текст, що набирається.

import React , { useState } from "react" ;

import "./styles.css" ;

function Form() {

const [ nameState , setNameState ] = useState ( " " );

const handlerSubmit = event => {

event .preventDefault ();

alert( nameState );

};

const handlerChange = event => {

setNameState ( event . target . value );

};

return (

< form onSubmit ={ handlerSubmit }>

< input type = "text" placeholder = "Input name" value ={ nameState } onChange ={ handlerChange } required />

< input type = "submit" value = "Click me" />

</ form >

);

}

export default function App() {

return (

<>< Form /></>

);

}

При створенні текстового поля ми вказали, що у нас є обробник змін у ньому

Це функція handlerChange .

const handlerChange = event => {

setNameState ( event.target.value );

};

У тілі функції ми беремо поточний набраний текст через event.target.value і оновлюємо стан через setNameState . Після оновлення змінної-стану,

React автоматично оновлює елемент керування, за яким вона закріплена

27 of 45

У наступному прикладі ми будемо аналізувати текст, що вводиться користувачем, і скасовувати введення, якщо поточне значення нас не влаштує. Зовнішній вигляд програми:

Ми заборонимо вводити test як ім'я. Цей проект створено за допомогою класових компонентів.

Код App.js :

import React , { Component } from "react" ;

import "./styles.css" ;

class UserForm extends Component {

state = {

nameState : "" ,

lastNameState : ""

};

render() {

const handlerSubmit = event => {

event .preventDefault ();

alert( this . state . nameState + " " + this . state . LastNameState );

};

Ми створюємо два змінних стани. По одній для кожного текстового поля

28 of 45

const handlerNameChanged = event => {

let name = event . target . value ;

if ( name .trim (). toUpperCase () === "TEST" ) {

alert( "Wrong name!" );

this .setState ({ nameState : "" });

} else {

this .setState ({ nameState: event . target . value });

}

};

const handlerLastNameChanged = event => {

this .setState ({ lastNameState : event . target . value });

};

return (

< form onSubmit ={ handlerSubmit }>

< input type = "text" className = " formElement " placeholder = "Input name" value = { this . state . nameState }

onChange ={ handlerNameChanged } required />

< input type = "text" className = " formElement " placeholder = "Input last name" value = { this . state . lastNameState } onChange ={ handlerLastNameChanged } required />

< input type = "submit" className = " formElement " value = "Send info" />

</ form >

);

}

}

Для перевірки значення у текстовому полі ми використовуємо обробник події onChange

Якщо значення дорівнює test , ми змінюємо змінну стану, записуючи до неї пусте значення.

Якщо значення не дорівнює test , тоді ми оновлюємо змінну стану, записуючи до неї поточне значення

29 of 45

export default class App extends Component {

render() {

return (

<> < UserForm /> </>

);

}

}

Завдання

  1. Створіть програму "Персональна сторінка". Використовуйте текстові поля для відображення частини інформації. Наприклад : ПІБ , телефон , email , місто проживання і т.д. Наявність текстових полів дозволяє користувачеві модифікувати вихідні дані. Також додайте кнопку для повернення початкових значень. Використовуйте state , класові компоненти.

2. Створіть реєстраційну форму. Користувач повинен вводити: нік, електронну адресу, стать, вік. Використовуйте можливості React для роботи з формами. Використовуйте React для валідації введених значень.

30 of 45

3. Створіть форму, щоб завантажити фотографію. Користувач повинен вводити нік, пароль, електронну адресу, фотографію, опис фотографії, теги. Використовуйте

можливості React до роботи з формами. Використовуйте React для валідації введених значень.

31 of 45

Робота із селектами

Робота з select практично не відрізняється від роботи з інпутами та чекбоксами .

Приклад:

function App() {

const [value, setValue ] = useState ('');

function handleChange (event) {

setValue ( event.target.value );

}

return <div>

< select value={ value } onChange ={ handleChange }>

<option> text1 </option>

<option> text2 </option>

<option> text3 </option>

<option> text4 </option>

</ select >

<p> ваш вибір : { value }</p>

</div>;

}

32 of 45

Атрибути value

Нехай тепер у нас у тегах option є атрибути value :

function App () {

return <div>

<select>

<option value = "1" > text1 </option>

<option value = "2" > text2 </option>

<option value = "3" > text3 </option>

</select>

</div> ;

}

В такому випадку через наявність _ атрибутів value у стейт будуть потрапляти саме їх значення , а не тексти тегів option . Можна, можливо переконатися в цьому , вивівши результат вибору абзацу:

33 of 45

function App () {

const [ value , setValue ] = useState ( '' ) ;

return <div>

<select value = { value } onChange = {( event ) => setValue ( event. target . value )} >

<option value = "1" > text1 </option>

<option value = "2" > text2 </option>

<option value = "3" > text3 </option>

</select>

<p> ваш вибір : { value } </p>

</div> ;

}

Розділити текст option та його значення може бути зручно :

текст тега ми можемо міняти як нам завгодно, при цьому у нашому скрипті результат вибору буде оброблятися за значенням атрибуту value , які залишиться незмінним :

34 of 45

function App () {

const [ value , setValue ] = useState ( '' ) ;

return <div>

<select value = { value } onChange = { event => setValue ( event. target . value )} >

<option value = "1" > text1 </option>

<option value = "2" > text2 </option>

<option value = "3" > text3 </option>

</select>

<p>

{ value === '1' && ' ви обрали перший пункт' }

{ value === '2' && ' ви обрали другий пункт' }

{ value === '3' && ' ви обрали третій пункт' }

</p> _

</div> ;

}

Тепер , якщо ми змінимо тексти option , то робота скрипта не порушиться - адже вона прив'язана до значення атрибуту value .

35 of 45

Приклад : Користувач вибирає у списку категорію фідбека. Пише текст і надсилає його при натисканні на кнопку « Send feedback ». У коді ми відобразимо інформаційне повідомлення з його даними, без надсилання даних на сервер.

У цьому прикладі ми будемо використовувати список та велике текстове поле. Код файлу UserForm.js (ми перейменували App.js ):

import React from "react" ;

import { useState } from "react" ;

import "./styles.css" ;

export default function UserForm () {

const [ selectedItem , setSelectedItem ] = useState ( "actors" );

const [ content , setContent ] = useState ( "" );

const handlerTextAreaChanged = event => {

setContent ( event . target . value );

};

const handlerSelectChanged = event => {

setSelectedItem ( event . target . value );

};

const handlerSubmit = event => {

event . preventDefault ();

const msg = `Your feedback about ${ selectedItem } : \n ${content}` ;

alert ( msg );

};

У коді прикладу ми перейменували компонент App у UserForm . Крім того, ми внесли нове ім'я, де це було необхідно ( у файлі index.js)

Ми використовуємо хук стану двічі. Змінна content

відповідатиме за текстове поле. Змінна selectedItem за список

36 of 45

return (

<div> _ _

< form onSubmit ={ handlerSubmit }>

< label > Please choose category of your feedback

< select value ={ selectedItem } onChange ={ handlerSelectChanged }>

< option >Service</ option >

< option >Products</ option >

< option >Shops</ option >

</ select >

</ label >

< Textarea value ={ content } onChange ={ handlerTextAreaChanged } placeholder = "Виберіть свій запис" required />

< input type = "submit" value = "Send feedback" />

</ form >

</ div >

);

}

Елемент списку, значення якого вказано у value , буде виділено. При старті це рядок з написом actors. Зверніть увагу, що у звичайному HTML виділення рядка використовується атрибут selected :

const [content, setContent ] = useState ("");

const [ selectedItem , setSelectedItem ] = useState ("actors");

37 of 45

Завдання 1

За допомогою списку, що випадає, запропонуйте користувачеві вибрати до якої вікової групи він відноситься: від 0 до 12 років, від 13 до 17, від 18 до 25, або старше 25 років.

Завдання 2

Зробіть список країн, що випадає. Зробіть абзац, в який буде виводитися вибір користувача. При виборі пункту вивести також до абзацу столицю вибраної країни. Використовуйте теги < option > без атрибуту

Завдання 3

Нехай у масиві зберігається список студентів. Виведіть за допомогою циклу список цих студентів. При виборі пункту списку виведіть у якій групі навчається цей студент . Використовуйте теги < option > c атрибутом value

Завдання 4

Нехай у масиві зберігається перелік міст. Виведіть за допомогою циклу список цих міст. При виборі пункту списку відобразити відповідну картинку в компоненті

38 of 45

Робота з чекбоксами

В елементах checkbox замість атрибуту value вказується атрибут checked . Якщо цей атрибут передати _ true - то чекбокс буде відзначений , а якщо false - не буде відзначений :

function App() {

return <div>

<input type="checkbox" checked ={true} /> відзначений

< input type="checkbox" checked ={false} /> не відзначений

</div> ;

}

Зазвичай в атрибут checked передається стейт , що містить логічне значення :

function App() {

const [checked, setChecked ] = useState ( true );

return <div>

<input type="checkbox" checked ={checked} />

</div>;

}

39 of 45

Так само, як і при роботі з інпутами , якщо жорстко поставити значення атрибуту checked - стан чекбоксу не можна буде змінити . Для коректної роботи будемо зі зміни чекбоксу міняти його стейт на протилежне йому значення :

function App() {

const [ checked , setChecked ] = useState (true);

function handleChange () {

setChecked ( ! Checked ); // інвертуємо стейт

}

return <div>

<input type="checkbox" checked ={ checked } onChange ={ handleChange } />

</div>;

}

Функцію handleChange можна і по-іншому написати:

function handleChange () {

setChecked ( val => ! val ); // інвертуємо стейт

}

40 of 45

Приклад : ми зробимо один обробник на два елементи керування. Також ми використовуємо елемент керування checkbox . Зовнішній вигляд програми:

Користувач вводить свою поштову адресу. Вказує

чи потрібна йому передплата новин. Після чого натискає

на кнопку з написом « Send data ». У коді ми відобразимо

інформаційне повідомлення з його даними, без посилання

даних на сервер. Код UserForm.js :

import React from "react" ;

import { useState } from "react" ;

import "./styles.css" ;

export default function UserForm () {

const [ news , setNews ] = useState ( true );

const [ email , setEmail ] = useState ( "" );

const handlerSubmit = event => {

event . preventDefault ();

let msg = "" ;

if ( news === true ) {

msg = "Thank you for subsсibe! \n " ;

}

msg += "Your email:" + email ;

alert ( msg );

};

41 of 45

/* Один обробник події на два input */

const handlerChanged = event => {

const target = event . target ;

/* Перевіряємо для якого елемента виникла подія */

target . name === " про News " ? setNews ( event . target . checked ) : setEmail ( target . value );

};

return (

<div> _ _

< form className = " userForm " onSubmit ={ handlerSubmit }>

< input name = " userEmail " type = "email" required placeholder = "email" value ={ email }

onChange = { handlerChanged } />

< input type = "checkbox" name = " про News " checked = { news } onChange ={ handlerChanged } />

< label >Чи ви збираєтесь повідомити новини?</ label >

< input type = "submit" value = "Send" />

</ form >

</ div >

);

}

Властивість checked визначає чи вибраний чекбокс . За цією властивістю ми закріплюємо нашу змінну стану. На onChange ми закріплюємо функцію-обробник handlerChanged . Ми вказали, що у чекбоксу атрибут name дорівнює aboutNews . Це значення нам знадобиться, коли ми перевірятимемо для якого елемента управління спрацював обробник onChange .

Щоб перевірити для якого елемента управління зголосився обробник, ми використовуємо властивість target.name . Якщо воно одно про News , значить обробник спрацював для чекбокса . І нам потрібно

оновити його стан, інакше обробник був викликаний для текстового поля. І тоді оновлення стану потрібне йому.

42 of 45

Робота з radio

Робота з radio дещо відрізняється, від чекбоксів . Проблема в тому, що у кількох radio буде той самий стейт, але різні value .

Тому робота відбувається так:

  • кожній радіокнопці в атрибут value записують своє значення, а в атрибут checked - спеціальна умова, яка перевіряє, чи стейт дорівнює певному значенню.
  • Якщо дорівнює – радіокнопка стане позначеною, а якщо не дорівнює – буде не позначеною.

function App () {

const [ value , setValue ] = useState ( 1 ) ;

function changeHandler ( event ) {

setValue ( event. target . value ) ;

}

return

<div>

<input type = "radio" name = "radio" value = "1" checked = { value === '1' ? true : false } onChange = { changeHandler } />

<input type = "radio" name = "radio" value = "2" checked = { value === '2' ? true : false } onChange = { changeHandler } />

<input type = "radio" name = "radio" value = "3" checked = { value === '3' ? true : false } onChange = { changeHandler } /> </div>

}

43 of 45

Розробіть програму для відображення списку користувачів. Ваше завдання - відображати список користувачів, використовуючи масив об'єктів користувачів, переданих через props і використовувати map для відображення кожного користувача у вигляді компонента.

  • Створіть компонент UserList , який прийматиме масив об'єктів користувачів як пропс.

  • Всередині компонента UserList створіть стан selectedUser , який міститиме вибраного користувача.

  • Використовуючи хук useState , ініціалізуйте стан selectedUser значенням null .

  • Створіть функцію handleUserClick , яка встановлюватиме вибраного користувача в стан selectedUser .

  • У компоненті UserList відобразіть список користувачів за допомогою map . Кожен користувач повинен відображатися як компонент з ім'ям UserItem . Для кожного користувача передайте props , що містить дані користувача та функцію handleUserClick .

  • Створіть компонент UserItem , який відображатиме дані користувача та додавати обробник події onClick для виклику функції handleUserClick з даними користувача як аргумент. Якщо вибрано цей користувач, необхідно додати клас selected до елемента.

  • При виборі користувача в стан selectedUser необхідно записати об'єкт вибраного користувача.

  • Відобразіть компонент UserList в іншому компоненті.

44 of 45

4. Користувач вибирає у списку категорію фідбека. Пише текст і надсилає його при натисканні на кнопку « Send feedback ». У коді ми відобразимо інформаційне повідомлення з його даними, без надсилання даних на сервер.

У цьому прикладі ми будемо використовувати список та велике текстове поле. Код файлу UserForm.js (ми перейменували App.js ):

45 of 45

Завдання 1

Даний чекбокс , кнопка та абзац. По кліку на кнопку, якщо чекбокс позначено, виведіть в абзац текст привітання з користувачем, а якщо не помічено - текст прощання.

Завдання 2

За допомогою трьох чекбоксів попросіть користувача вибрати мови, які він знає: html , css та js . Результат вибору кожної мови виводьте в окремі абзаци.

Завдання 3

Дано 3 радіокнопки. Дано абзац. Зробіть так, щоб значення вибраної радіокнопки виводилося до цього абзацу.

Завдання 4

За допомогою радіокнопок запитайте у користувача його улюблену мову програмування. Виведіть його вибір до абзацу. Якщо вибрано JavaScript, похваліть користувача.

Завдання 5

Створіть компонент RadioForm , який містить групу радіо-кнопок з опціями "Варіант 1", "Варіант 2" та "Варіант 3". Коли користувач вибирає одну з опцій, виведіть на екран вибраний варіант.

Розширте попереднє завдання, додавши кнопку "Скинути". При натисканні на цю кнопку скидайте вибір та очищайте всі радіокнопки.

Завдання 6

Створіть компонент DynamicRadioForm , який отримує масив об'єктів опцій у форматі { id :1, label : 'Опція 1'}. Відобразіть радіокнопки на основі цього масиву. При виборі опції виведіть вибраний елемент на екран.

Завдання 7

Реалізуйте компонент ConditionalRadioForm , який містить дві групи радіокнопок. При виборі однієї опції в першій групі відображайте другу групу радіо-кнопок. Якщо вибрано іншу опцію в першій групі, приховайте другу групу.