Здесь я буду предельно краток: facebook выкатили удобный инструмент для старта приложения. Поддерживается новый синтаксис, импорты, тестирование, перезагрузка страницы при изменениях, линтер и многое другое.
Во всем разнообразии мы сейчас разбираться не будем. Цель: разбить index.html на компоненты, подключить их, навести порядок.
Скопируйте index.html куда-нибудь на память, скоро мы разобьем его на мелкие удобные компоненты.
Установка и запуск create-react-app
npx create-react-app my-appcd my-appnpm start
Если вы не знакомы с данными командами, значит вам нужно поставить себе node.js и ввести их в терминале после.
После запуска мы получим следующую картину в браузере:
И следующую файловую структуру:
+-- node_modules (здесь расположены пакеты для работы приложения)+-- public (здесь расположены публичные файлы, такие как index.html и favicon)+-- src (здесь сейчас уже живет компонент App)+-- .gitignore (файл для гита)+-- package.json (файл с зависимостями проекта)+-- README.md (описание проекта)+-- yarn.lock (может быть, а может и не быть - тоже относится к теме зависимостей проекта)
Восстановим баланс в src
src/App.css (копируем все наши стили)
.none {display: none;}body {background: rgba(0, 102, 255, 0.38);font-family: sans-serif;}p {margin: 0 0 5px;}.article {background: #FFF;border: 1px solid rgba(0, 89, 181, 0.82);width: 600px;margin: 0 0 5px;box-shadow: 2px 2px 5px -1px rgb(0, 81, 202);padding: 3px 5px;}.news__author {text-decoration: underline;color: #007DDC;}.news__count {margin: 10px 0 0 0;display: block;}.test-input {margin: 0 5px 5px 0;}.add {margin: 0 5px 5px 0;width: 210px;border: 1px dashed rgba(0, 89, 181, 0.82);padding: 5px;}.add__author, .add__text, .add__btn, .add__checkrule {display: block;margin: 0 0 5px 0;padding: 5px;width: 94%;border: 1px solid rgba(0, 89, 181, 0.82);}.add__checkrule {border: none;font-size: 12px;}.add__btn {box-sizing: content-box;color: #FFF;text-transform: uppercase;background: #007DDC;}.add__btn:disabled {background: #CCC;color: #999;}
src/App.js (копируем почти все из тэга script)
import React from 'react'; // подключение библиотеки Reactimport './App.css'; // подключение файла стилей// далее скопировано из тэга scriptconst myNews = [{id: 1,author: "Саша Печкин",text: "В четверг, четвертого числа...",bigText:"в четыре с четвертью часа четыре чёрненьких чумазеньких чертёнка чертили чёрными чернилами чертёж."},{id: 2,author: "Просто Вася",text: "Считаю, что $ должен стоить 35 рублей!",bigText: "А евро 42!"},{id: 3,author: "Max Frontend",text: "Прошло 2 года с прошлых учебников, а $ так и не стоит 35",bigText: "А евро опять выше 70."},{id: 4,author: "Гость",text: "Бесплатно. Без смс, про реакт, заходи - https://maxpfrontend.ru",bigText:"Еще есть группа VK, telegram и канал на youtube! Вся инфа на сайте, не реклама!"}];class Article extends React.Component {state = {visible: false};handleReadMoreClck = e => {e.preventDefault();this.setState({ visible: true });};render() {const { author, text, bigText } = this.props.data;const { visible } = this.state;return (<div className="article"><p className="news__author">{author}:</p><p className="news__text">{text}</p>{!visible && (<aonClick={this.handleReadMoreClck}href="#"className="news__readmore">Подробнее</a>)}{visible && <p className="news__big-text">{bigText}</p>}</div>);}}Article.propTypes = {data: PropTypes.shape({id: PropTypes.number.isRequired, // добавили id, это число, обязательноauthor: PropTypes.string.isRequired,text: PropTypes.string.isRequired,bigText: PropTypes.string.isRequired})};class News extends React.Component {renderNews = () => {const { data } = this.props;let newsTemplate = null;if (data.length) {newsTemplate = data.map(function(item) {return <Article key={item.id} data={item} />;});} else {newsTemplate = <p>К сожалению новостей нет</p>;}return newsTemplate;};render() {const { data } = this.props;return (<div className="news">{this.renderNews()}{data.length ? (<strong className={"news__count"}>Всего новостей: {data.length}</strong>) : null}</div>);}}News.propTypes = {data: PropTypes.array.isRequired};class Add extends React.Component {state = {name: "",text: "",bigText: "",agree: false};onBtnClickHandler = e => {e.preventDefault();const { name, text, bigText } = this.state;this.props.onAddNews({id: +new Date(),author: name,text,bigText});};handleChange = e => {const { id, value } = e.currentTarget;this.setState({ [id]: e.currentTarget.value });};handleCheckboxChange = e => {this.setState({ agree: e.currentTarget.checked });};validate = () => {const { name, text, agree } = this.state;if (name.trim() && text.trim() && agree) {return true;}return false;};render() {const { name, text, bigText, agree } = this.state;return (<form className="add"><inputid="name"type="text"onChange={this.handleChange}className="add__author"placeholder="Ваше имя"value={name}/><textareaid="text"onChange={this.handleChange}className="add__text"placeholder="Текст новости"value={text}/><textareaid="bigText"onChange={this.handleChange}className="add__text"placeholder="Текст новости подробно"value={bigText}/><label className="add__checkrule"><input type="checkbox" onChange={this.handleCheckboxChange} /> Ясогласен с правилами</label><buttonclassName="add__btn"onClick={this.onBtnClickHandler}disabled={!this.validate()}>Показать alert</button></form>);}}Add.propTypes = {onAddNews: PropTypes.func.isRequired};class App extends React.Component {state = {news: myNews};handleAddNews = data => {const nextNews = [data, ...this.state.news];this.setState({ news: nextNews });};render() {return (<React.Fragment><Add onAddNews={this.handleAddNews} /><h3>Новости</h3><News data={this.state.news} /></React.Fragment>);}}// скопировано все кроме ReactDOM.render// добавился exportexport default App;
Удалите файл src/Logo.svg
, остальное не трогайте, но можете посмотреть :)
Create-react-app (CRA) при каждом изменении в файлах внутри директории src - перезагружает страницу в браузере.
У нас нет PropTypes в проекте. Так как раньше это был тэг script, а теперь нам нужен npm-пакет.
Остановите работу create-react-app в терминале и добавьте пакет prop-types
npm install --save prop-types
Я не привожу сюда примеров для yarn, так как если у вас yarn вы итак в курсе, как ставить пакеты через него.
Подключите PropTypes в начале файла:
src/App.js
import React from 'react'import PropTypes from 'prop-types'import './App.css'...
Запустите приложение еще раз:
npm start
Итого: мы перевели приложение на CRA.
Исходный код на данный момент (добавлен конфиг для преттира - .prettierrc, не обращайте внимание).