6.6 KiB
id, title, challengeType, forumTopicId, dashedName
id | title | challengeType | forumTopicId | dashedName |
---|---|---|---|---|
5a24c314108439a4d4036189 | Зміна вбудованих CSS умовно на основі стану компонента | 6 | 301380 | change-inline-css-conditionally-based-on-component-state |
--description--
На цьому етапі вже було опрацьовано декілька додатків умовної візуалізації та використання вбудованих стилів. Розглянемо ще один приклад, що поєднує ці дві теми. Також можна відтворити CSS умовно на основі стану компонента React. Для цього необхідно перевірити умову, і якщо вона виконана, змінити об’єкт стилів, призначений для елементів JSX методом візуалізації.
Цю парадигму важливо зрозуміти, оскільки вона є різкою зміною від більш традиційного підходу до застосування стилів шляхом безпосередньої зміни елементів DOM (що дуже часто зустрічається, наприклад, з jQuery). При такому підході необхідно відстежувати момент зміни елементів, а також безпосередньо обробляти фактичне керування. При відстежуванні змін можуть виникнути складнощі, що потенційно робить ваш інтерфейс непередбачуваним. Встановлюючи об’єкт стилю на основі умови, опишіть, що інтерфейс має виглядати як функція стану додатку. Існує чіткий потік інформації, який рухається тільки в одному напрямку. Це найбільш прийнятний метод під час написання програм з React.
--instructions--
Редактор коду має простий керований компонент введення зі стилізованою рамкою. У разі застосування користувачем понад 15 символів тексту у полі введення, можна оформити цю рамку у червоний колір. Для перевірки, додайте умову, і, вона є дійсною, встановіть стиль введення меж для 3px solid red
. Щоб спробувати його, введіть текст у відповідне поле.
--hints--
Компонент GateKeeper
повинен відображати елемент div
.
assert(
(function () {
const mockedComponent = Enzyme.mount(React.createElement(GateKeeper));
return mockedComponent.find('div').length === 1;
})()
);
Компонент GateKeeper
слід ініціалізувати ключем стану input
, встановленим для порожнього рядка.
assert(
(function () {
const mockedComponent = Enzyme.mount(React.createElement(GateKeeper));
return mockedComponent.state().input === '';
})()
);
Компонент GateKeeper
повинен відображати тег h3
і тег input
.
assert(
(function () {
const mockedComponent = Enzyme.mount(React.createElement(GateKeeper));
return (
mockedComponent.find('h3').length === 1 &&
mockedComponent.find('input').length === 1
);
})()
);
Теґ input
спочатку повинен мати стиль 1px solid black
для властивості border
.
assert(
(function () {
const mockedComponent = Enzyme.mount(React.createElement(GateKeeper));
return (
mockedComponent.find('input').props().style.border === '1px solid black'
);
})()
);
Теґ input
має бути оформлений з рамкою 3px solid red
, якщо введене значення в стані перевищує 15 символів.
async () => {
const waitForIt = (fn) =>
new Promise((resolve, reject) => setTimeout(() => resolve(fn()), 100));
const mockedComponent = Enzyme.mount(React.createElement(GateKeeper));
const simulateChange = (el, value) =>
el.simulate('change', { target: { value } });
let initialStyle = mockedComponent.find('input').props().style.border;
const state_1 = () => {
mockedComponent.setState({ input: 'this is 15 char' });
return waitForIt(() => mockedComponent.find('input').props().style.border);
};
const state_2 = () => {
mockedComponent.setState({
input: 'A very long string longer than 15 characters.'
});
return waitForIt(() => mockedComponent.find('input').props().style.border);
};
const style_1 = await state_1();
const style_2 = await state_2();
assert(
initialStyle === '1px solid black' &&
style_1 === '1px solid black' &&
style_2 === '3px solid red'
);
};
--seed--
--after-user-code--
ReactDOM.render(<GateKeeper />, document.getElementById('root'))
--seed-contents--
class GateKeeper extends React.Component {
constructor(props) {
super(props);
this.state = {
input: ''
};
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({ input: event.target.value })
}
render() {
let inputStyle = {
border: '1px solid black'
};
// Change code below this line
// Change code above this line
return (
<div>
<h3>Don't Type Too Much:</h3>
<input
type="text"
style={inputStyle}
value={this.state.input}
onChange={this.handleChange} />
</div>
);
}
};
--solutions--
class GateKeeper extends React.Component {
constructor(props) {
super(props);
this.state = {
input: ''
};
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({ input: event.target.value })
}
render() {
let inputStyle = {
border: '1px solid black'
};
if (this.state.input.length > 15) {
inputStyle.border = '3px solid red';
};
return (
<div>
<h3>Don't Type Too Much:</h3>
<input
type="text"
style={inputStyle}
value={this.state.input}
onChange={this.handleChange} />
</div>
);
}
};