Из заголовка поста вы понимаете, что я не только собираюсь объяснить, как реализовать традиционный TODO-List с помощью React, но также покажу вам, как я применяю Emotion-js для этого. мини-проект.
Начнем с настройки нового приложения React, следуя официальной документации здесь.
После этого мы напишем простой TODO-List. Я решил просто поместить приведенный ниже код, потому что основной смысл сообщения заключается в использовании библиотеки Emotion для стилизации извлеченных компонентов.
Простой TODO-список с React:
// TodoList.js import React from 'react'; export const TodoList = (props) => { return( <ul> {props.todoItems.map((todo, index) => <li key={index}>{todo}</li> )} </ul> ); };
а также
// App.js import React, {Component} from 'react'; import './App.css'; import {TodoList} from './TodoList'; class App extends Component { constructor() { super(); this.state = { inputValue: '', todoItems: [] }; this.onChangeInputValue = this.onChangeInputValue.bind(this); this.onSubmitInputValue = this.onSubmitInputValue.bind(this); } onChangeInputValue(event) { this.setState({ inputValue: event.target.value }); } onSubmitInputValue(event) { event.preventDefault(); this.setState({ inputValue: '', todoItems: [...this.state.todoItems, this.state.inputValue] }); } render() { return ( <div> <form onSubmit={this.onSubmitInputValue}> <input type="text" value={this.state.inputValue} onChange={this.onChangeInputValue}/> <button>Create</button> </form> <TodoList todoItems={this.state.todoItems}/> </div> ); } } export default App;
Я хотел бы иметь компонент со стилем Emotion, который принимает реквизиты, которые в конечном итоге управляют стилем. Более того, любое выражение или интерполяция может быть функцией, а классы CSS - это то, что мы генерируем, когда используем модули SCSS / CSS. Это убедительный шаблон, который можно использовать для создания повторно используемых стилей в любом проекте.
Итак, следующим шагом будет установка наиболее полезных пакетов Emotion:
npm install --save emotion react-emotion babel-plugin-emotion
Вместо того, чтобы стилизовать элементы DOM с помощью CSS, я создал Стилизованные компоненты, чтобы затем я мог вызывать его с помощью литерала шаблона для стилей строк везде в проекте, который мне нужен.
Поскольку я предпочитаю планирование и стилизацию из контейнеров и оболочек (особенно, если я использую для этого flexbox), я начал с извлечения, стилизации и использования компонентов ‹Container /› и ‹Wrapper /›.
// App.js ... // importing styled method import styled from 'react-emotion'; ... // declaring a new component const Container = styled('div')` display: flex; overflow: hidden; justify-content: center; height: 100vh; align-items: center; font-family: 'Source Sans Pro', sans-serif; flex-direction: column; box-shadow: 0 0 5px rgba(25, 25, 25, 0.25); `; const Wrapper = styled('div')` display: flex; flex-direction: column; background: white; border-radius: 20px; `; class App extends Component { ... render() { return ( // applying components <Container> <Wrapper> <form onSubmit={this.onSubmitInputValue}> ... </Wrapper> </Container> ); } } export default App;
Затем я создал компоненты: ‹CreateTodoForm /›, ‹CreateTodoInput /› и ‹CreateTodoButton /› для стилизации формы, разделил их на js-файлы и импортировал в App.js.
// CreateTodoForm.js import React from 'react'; import styled from 'react-emotion'; export const CreateTodoForm = styled('form')` width: 400px; padding: 1rem; display: flex; border-radius: 20px; `;
а также
// CreateTodoInput.js import React from 'react'; import styled from 'react-emotion'; export const CreateTodoInput = styled('input')` width: 100%; font-size: 14px; margin: 0 0.5rem; border-radius: 2rem; padding: .75em 1.5rem; background: none; border: #e3e3e3 1px solid; transition: border 250ms ease-out; &:focus { border: #4fc08d 1px solid; outline: none; } `;
а также
// CreateTodoButton.js import React from 'react'; import styled from 'react-emotion'; export const CreateTodoButton = styled('button')` font-size: 14px; margin: 0 0.5em; border-radius: 2em; padding: 0.75em 1.5em; cursor: pointer; background: none; border: 1px solid #4fc08d; letter-spacing: 1px; font-family: "Source Sans Pro", sans-serif; color: #4fc08d; transition: 250ms ease-out; &:hover, &:focus { color: #fff; background: #4fc08d; outline: none; } `;
тогда
// App.js import React, {Component} from 'react'; import styled from 'react-emotion'; import './App.css'; import {TodoList} from './TodoList'; // importing form-components import {CreateTodoInput} from './components/CreateTodoInput'; import {CreateTodoButton} from './components/CreateTodoButton'; import {CreateTodoForm} from './components/CreateTodoForm'; const Container = styled('div')` display: flex; overflow: hidden; justify-content: center; height: 100vh; align-items: center; font-family: 'Source Sans Pro', sans-serif; flex-direction: column; box-shadow: 0 0 5px rgba(25, 25, 25, 0.25); `; const Wrapper = styled('div')` display: flex; flex-direction: column; background: white; border-radius: 20px; `; class App extends Component { constructor() { super(); this.state = { inputValue: '', todoItems: [] }; this.onChangeInputValue = this.onChangeInputValue.bind(this); this.onSubmitInputValue = this.onSubmitInputValue.bind(this); } onChangeInputValue(event) { this.setState({ inputValue: event.target.value }); } onSubmitInputValue(event) { event.preventDefault(); this.setState({ inputValue: '', todoItems: [...this.state.todoItems, this.state.inputValue] }); } render() { return ( <Container> <Wrapper> // applying components to render them <CreateTodoForm onSubmit={this.onSubmitInputValue}> <CreateTodoInput type="text" value={this.state.inputValue} onChange={this.onChangeInputValue}/> <CreateTodoButton>Create</CreateTodoButton> </CreateTodoForm> <TodoList todoItems={this.state.todoItems}/> </Wrapper> </Container> ); } } export default App;
Вот окончательный результат:
На сегодня все. Надеюсь, вам понравится мое небольшое объяснение! Спасибо за чтение! 👏