👆Привет всем! В этом руководстве мы создадим простое приложение со списком задач с помощью React и хуков через интерфейс Context API Material UI и, наконец, интеграцию с Firebase 🔥
Часть 1: Установки и конфигурации
- Node.js и Npm ( https://nodejs.org/en/download/)
- VSCode (https://code.visualstudio.com/download)
Откройте терминал / cmd и введите:
$ sudo npm install -g create-react-app $ create-react-app todo-list $ cd todo-list
Добавить интерфейс материала
$ npm i --save@material-ui/core
$npm install @material-ui/icons
Перейдите в общую папку, откройте файл index.html и введите
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />
Добавить генератор UUID
$ npm i --save uuid
Часть 2: Контекстный API
В этой части статьи мы покажем, как использовать и реализовывать контекстный API и редукторы.
Итак, давайте начнем с создания двух папок:
- контексты
- редукторы
Давайте создадим файл TaskContext.js в папке контекста.
Контекст предоставляет способ передавать данные через дерево компонентов без необходимости передавать реквизиты вручную на каждом уровне.
- Создайте функцию компонента стрелки с помощью props:
export const TaskContext = createContext(); const TaskContextProvider = (props) => { ... } export default TaskContextProvider;
Затем нам нужно вернуть нашего провайдера с элементами диспетчера и задач, наконец, нам нужно реализовать «отсортированный массив», который возвращает отсортированные задачи по isCheked или Not.
return ( <TaskContext.Provider value={{ tasks,sortedTasks, dispatch }}> {props.children} </TaskContext.Provider>)
Результат:
2. В папке reducer создайте новый файл reducer под названием TaskReducer.js.
Итак, нам нужен метод 3 действий для работы с нашим массивом задач: первое действие необходимо для добавления новой задачи, второе - для проверки задачи, а третье удалит задачу.
Давайте создадим перечисление для этих статических действий
export const Action = { ADD_TASK: "add-task", CHECK_TASK: "check-task", REMOVE_TASK: "remove-task" }
Давайте создадим редуктор с корпусом переключателя, чтобы заменить тип действия:
Когда добавление задачи выбрано, правильным способом будет выдвинуть новую задачу.
case Action.ADD_TASK: { return [...state, action.task] }
Когда выбран отмеченный тип, нам нужно изменить конкретную задачу в массиве по значению идентификатора задачи.
case Action.CHECK_TASK:{ let taskIndex = state.findIndex(t => t.id === action.task.id); state[taskIndex].isChecked = action.task.isChecked return state.filter(task => task.id !== action.id); }
И удалить задачу будет
case Action.REMOVE_TASK: { return state.filter(task => task.id !== action.id) }
Результат:
Часть 3: Компонент, хуки и UI материала
В этой части статьи мы узнаем, как создать компонент стрелочной функции для каждого события задачи.
Давайте создадим папку components в папке src и создадим 4 компонента:
- NavbarComponent.js - src / components / NavbarComponent.js
- AddTaskComponent.js - src / components / TodoListComponent.js.
- TasksListComponent.js - src / components / tasks / AddTaskComponent.js.
- TodoListComponent.js - src / component / tasks / TaskListComponent.js
Примечание: я решил создать еще одну папку в компонентах, называемых задачами.
- Откройте NavbarComponent.js, давайте создадим новый компонент и используем контекст
const NavbarComponent = () => { const {tasks} = useContext(TaskContext) } export default NavbarComponent;
Теперь давайте сделаем навигационную панель, используя материальный интерфейс.
return ( <AppBar position="static"> <Toolbar variant="dense" style={{ justifyContent: "center" }} > <Typography variant="h6" color="inherit"> React Todo List ({tasks.length}) </Typography> </Toolbar> </AppBar> );
Результат:
Https://gist.github.com/shai-benshimol/6a0872107dc9467a3859a9832b60a95c
2. Давайте создадим простой компонент для добавления новой задачи.
3. Давайте создадим новую функцию компонента - TasksListComponent и реализуем useStyles для фонового списка.
const useStyles = makeStyles((theme) => ({ root: { width: '100%', backgroundColor: theme.palette.background.transparent, }, marked: { textDecoration: 'line-through' } }));
Затем нам нужно использовать контекст задачи для возврата данных из редуктора.
const { sortedTasks, dispatch, } = useContext(TaskContext)
Затем верните jsx, используя материальный интерфейс.
return ( <List className={classes.root}> {sortedTasks.map((task) => { return ( <ListItem key={task.id} role={undefined} dense button onClick={() => { onChecked(task.id, !task.isChecked) } }> <IconButton color="primary"> { !task.isChecked ? (<CropFreeIcon />) : (<LibraryAddCheckIcon />) } </IconButton> <ListItemText primary={task.description} className={task.isChecked ? classes.marked : ''} /> <ListItemSecondaryAction> <IconButton edge="end" aria-label="comments" onClick={() => { dispatch({ type: Action.REMOVE_TASK, id: task.id }) }}> <DeleteOutlineIcon /> </IconButton> </ListItemSecondaryAction> </ListItem> ); })} </List>
Результат:
4. Откройте созданный ранее TodoListComponent.js и создайте новый компонент для этого состояния.
В TodoListComponent мы хотим объединить 2 компонента, AddTask и TasksList, в столбец.
Давайте соберем все вместе в App.js… Итак, откройте файл App.js и замените его на
И это все
$ npm run start
Часть 4: Firebase
Я уже создал руководство по интеграции firebase
Создайте список задач с помощью Vuejs, Vuex, Vuetify и Firebase 🔥
🔭Сегодня я собираюсь показать вам, как создать приложение с нуля, используя самый мощный фреймворк SPA Vuejs ”С… medium.com»
Теперь давайте создадим новую папку для firebase с двумя подпапками: firebase.config.js и Firebase.js.
В firebase.config.js просто добавьте свои значения из консоли firebase, как:
import firebase from 'firebase';const firebaseConfig = { apiKey: "<--->", authDomain: "<--->", databaseURL: "<--->", projectId: "<--->", storageBucket: "<--->", messagingSenderId: ""<--->", appId: "<--->", measurementId: "<--->" };firebase.initializeApp(firebaseConfig)export const db = firebase.firestore()
Откройте «Firebase.js» и добавьте 4 функции.
- addTaskReques
- getTasksRequest
- checkTaskRequest
- removeTaskRequest
Добавить запрос задачи:
export const addTaskRequest = async (task) => { return await db.collection(collection) .add(task) }
Получить запрос задач
export const getTasksRequest = async () => { return await db.collection(collection).get().then(res => { let tasks = []; res.docs.map(task => { let data = task.data(); tasks.push({ id: data.id, isChecked: data.isChecked, description: data.description, created: data.created }) }) return tasks; }) }
Проверить запрос задачи
export const checkTaskRequest = (id, isChecked) => { return db.collection(collection) .doc(id) .set({ isChecked: isChecked }) }
Удалить запрос задачи
export const removeTaskRequest = (id) => { return await db.collection(collection) .db.collection(collection) .doc(id) .delete() }
Конечный результат
Часть 5: useEffect
Обработчик эффекта, useEffect, добавляет возможность выполнять побочные эффекты из функционального компонента. Он служит той же цели, что и componentDidUpdate и componentWillUnmount в классах React, но объединен в единый API. (Мы покажем примеры сравнения useEffect с этими методами в Использование обработчика эффектов.)
Теперь давайте внесем некоторые изменения в «TaskComponent.js», создадим массив useState для setTasks из хранилища firebase, а затем создадим хук useEffect следующим образом:
const [sortedTasks,setTasks] = useState([]); const count = sortedTasks.length; useEffect(()=>{ getTasksRequest().then(res=>{ setTasks(res.sort((t, f) => (f.isChecked === t.isChecked)? 0 : f.isChecked? -1 : 1)) dispatch({ type:Action.GET_ALL_TASKS, res }) }) },[])
Конечный результат
Вывод
Мы узнали, как обрабатывать локальное состояние с помощью Context API и хуков, создавать пользовательский интерфейс с пользовательским интерфейсом материала и хранить данные в облаке firebase.