استفاده از ریداکس در اپلیکیشن ری اکت — راهنمای کاربردی

۲۱۷ بازدید
آخرین به‌روزرسانی: ۰۳ مهر ۱۴۰۲
زمان مطالعه: ۴ دقیقه
استفاده از ریداکس در اپلیکیشن ری اکت — راهنمای کاربردی

فرض کنید تصمیم گرفته‌اید از ریداکس (Redux) به عنوان کتابخانه مدیریت حالت استفاده کنید. باور کنید یا نه این بخش یعنی تصمیم‌گیری در مورد کتابخانه‌ای که باید استفاده شود، سخت‌ترین بخش کار است. بقیه مراحل آسان و سریع هستند. در این راهنما با ما همراه باشید تا در عرض چند دقیقه با استفاده از ریداکس در اپلیکیشن ری اکت یک نرم‌افزار ToDo بسازیم.

معرفی ریداکس

ریداکس سه کامپوننت عمده به نام‌های store ،reducer و actions دارد. بر اساس مستندات ریداکس:

  • کامپوننت Store «حالت» (State) (درخت حالت) اپلیکیشن را نگهداری می‌کند. تنها روش برای تغییر حالت درون آن، این است که یک اکشن را به آن ارسال (Dispatch) کنید.
  • کامپوننت Actions در واقع payload اطلاعاتی است که داده‌ها را از اپلیکیشن به استور ارسال می‌کنند. اکشن‌ها تنها منبع اطلاعات برای استور محسوب می‌شوند.

ما دو اکشن تعریف می‌کنیم که createItem و deleteItem هستند.

  • «ردیوسرها» (Reducers) نیز شیوه مدیریت حالت از سوی اپلیکیشن را در پاسخ به اکشن‌های ارسال شده به استور تعیین می‌کنند. به خاطر داشته باشید که اکشن‌ها صرفاً آن چه رخ داده را توصیف می‌کنند، اما چگونگی تغییر یافتن حالت اپلیکیشن را توضیح نمی‌دهند.

یک ردیوسر در فرایندی شبیه به ایجاد یک جدول در پایگاه داده SQL ایجاد می‌شود. شیوه ساختن آن، بسته به نوع اپلیکیشن متفاوت خواهد بود.

راهنمای عملی

در این بخش مراحل راهنمای عملی ساخت اپلیکیشن ToDo و استفاده از ریداکس را توضیح می‌دهیم.

گام 1

با استفاده از اسکریپت create-react-app یک اپلیکیشن جدید ری‌اکت بسازید:

create-react-app todo-app

گام 2

وابستگی‌ها را با دستور زیر نصب کنید:

npm install lodash @material-ui/core @material-ui/icons react-redux redux redux-logger

گام 3

اگر می‌خواهید روشی مؤثر برای ذخیره فایل‌ها بیابید، از ساختار فایل ducks بهره بگیرید. اما در این راهنما به منظور سادگی از ساختار فایل ساده‌ای استفاده می‌کنیم.

پوشه جدیدی به نام modules ایجاد کنید. سپس سه فایل به نام‌های action.js، reducer.js و store.js در این پوشه بسازید. Actions اشیای ساده‌ای با یک خصوصیت الزامی به نام type هستند. اکشن‌ها را از کامپوننت Dispatch می‌کنیم تا داده‌ها به حالت استور ارسال شوند:

فایل Actions.js

1// types of action
2const Types = {
3  CREATE_ITEM: "CREATE_ITEM",
4  DELETE_ITEM: "DELETE_ITEM"
5};
6// actions
7const createItem = task => ({
8  type: Types.CREATE_ITEM,
9  payload: task
10});
11
12const deleteItem = id => ({
13  type: Types.DELETE_ITEM,
14  payload: id
15});
16
17export default {
18  createItem,
19  deleteItem,
20  Types
21};

روش بهینه این است که یک فایل دیگر برای نوع اکشن‌ها ایجاد کنید. به این منظور فایل reducer.js را ساخته و محتوای زیر را به آن اضافه می‌کنیم:

1import ACTIONS from "./action";
2import _ from "lodash";
3
4const defaultState = {
5  items: []
6};
7
8const todoReducer = (state = defaultState, action) => {
9  switch (action.type) {
10    case ACTIONS.Types.CREATE_ITEM: {
11      console.log(action);
12
13      let item = action.payload;
14      let newItem = { id: state.items.length + 1, description: item };
15      let newState = _.cloneDeep(state);
16      newState.items.push(newItem);
17      return newState;
18    }
19
20    case ACTIONS.Types.DELETE_ITEM: {
21      let newState = _.cloneDeep(state);
22      let index = _.findIndex(newState.items, { id: action.payload });
23      newState.items.splice(index, 1);
24      return newState;
25    }
26
27    default:
28      return state;
29  }
30};
31
32export default todoReducer;

فایل store.js نیز کدهایی به شکل زیر دارد:

1import { createStore, applyMiddleware } from "redux";
2
3// Logger with default options
4import logger from "redux-logger";
5
6import reducer from "./reducer";
7
8export default function configureStore(initialState) {
9  const store = createStore(reducer, initialState, applyMiddleware(logger));
10  return store;
11}

گام 4

فایل جدیدی به نام todo.js در پوشه جدیدی به نام pages درون پوشه src بسازید. این فایل شامل کامپوننت لیست ToDo خواهد بود. در این مثال روی ریداکس متمرکز شده‌ایم، بنابراین تلاش نمی‌کنیم که کامپوننت/کانتینر ایجاد کنیم. کل اپلیکیشن ما درون همین تک فایل قرار خواهد داشت. UI را با یک فرم و یک لیست برای نمایش وظیفه‌ها ایجاد می‌کنیم.

فایل todo.js

1import React, { Component } from "react";
2import {
3  withStyles,
4  List,
5  ListItem,
6  ListItemSecondaryAction,
7  ListItemText,
8  IconButton,
9  Grid,
10  TextField,
11  Button,
12  FormControl
13} from "@material-ui/core";
14import DeleteIcon from "@material-ui/icons/Delete";
15
16const styles = theme => ({
17  root: {
18    flexGrow: 1,
19    maxWidth: 752
20  },
21  demo: {
22    backgroundColor: theme.palette.background.paper
23  },
24  title: {
25    margin: `${theme.spacing.unit * 4}px 0 ${theme.spacing.unit * 2}px`
26  }
27});
28
29class ToDO extends Component {
30  state = {};
31
32  generate = () => {
33    return this.props.items.map(item => (
34      <ListItem key={item.id}>
35        <ListItemText primary={item.description} />
36        <ListItemSecondaryAction>
37          <IconButton
38            aria-label="Delete"
39            onClick={this.handleDelete}
40            value={item.id}
41          >
42            <DeleteIcon />
43          </IconButton>
44        </ListItemSecondaryAction>
45      </ListItem>
46    ));
47  };
48
49  handleSubmit = event => {
50    // console.log(this.state.item);
51    this.setState({ item: "" });
52    if (this.state.item !== "") {
53      // add the task to store
54
55    }
56    event.preventDefault();
57  };
58  handleDelete = event => {
59    //delete the task from the store
60    
61  };
62  handleChange = event => {
63    this.setState({
64      [event.target.name]: event.target.value
65    });
66  };
67
68  render() {
69    const { classes } = this.props;
70
71    return (
72      <div>
73        <div>
74          <form noValidate autoComplete="off" onSubmit={this.handleSubmit}>
75            <FormControl>
76              <TextField
77                label="New Task"
78                id="margin-dense"
79                value={this.state.item}
80                className={classes.textField}
81                margin="dense"
82                name="item"
83                onChange={this.handleChange}
84              />
85            </FormControl>
86            <FormControl>
87              <Button>Add</Button>
88            </FormControl>
89          </form>
90        </div>
91        <div>
92          <Grid item container justify="space-evenly" alignItems="center">
93            <div className={classes.demo}>
94              <List dense={false}>{this.generate()}</List>
95            </div>
96          </Grid>
97        </div>
98      </div>
99    );
100  }
101}
102
103export default withStyles(styles)(ToDO);

گام 5

اینک زمان آن رسیده است که کامپوننت todo را به استور ریداکس وصل کنیم. به این منظور فایل App.js را باز کنید و ارائه‌دهنده ریداکس را اضافه کنید تا همه فرزندان بتوانند به استور دسترسی داشته باشند:

1import React, { Component } from "react";
2import logo from "./logo.svg";
3import "./App.css";
4import ToDO from "./pages/todo";
5import { Provider as ReduxProvider } from "react-redux";
6import configureStore from "./modules/store";
7
8const reduxStore = configureStore(window.REDUX_INITIAL_DATA);
9
10class App extends Component {
11  render() {
12    return (
13      <ReduxProvider store={reduxStore}>
14        <div className="App">
15          <header className="App-header">
16            <img src={logo} className="App-logo" alt="logo" />
17            <h1 className="App-title">ToDo Redux app</h1>
18          </header>
19          <ToDO />
20        </div>
21      </ReduxProvider>
22    );
23  }
24}
25
26export default App;

درون فایل todo.js آن را با استفاده از کامپوننت connect از react-redux به استور وصل کنید. این موارد را به انتهای فایل todo.js اضافه کنید. اکنون آیتم‌های استور در props کامپوننت نیز در دسترس هستند. ضمناً دو تابع (اکشن) دیگر نیز در props موجود خواهند بود.

1import ACTIONS from "../modules/action";
2import { connect } from "react-redux";
3
4const mapStateToProps = state => ({
5  items: state.items
6});
7
8const mapDispatchToProps = dispatch => ({
9  createItem: item => dispatch(ACTIONS.createItem(item)),
10  deleteItem: id => dispatch(ACTIONS.deleteItem(id))
11});
12
13export default connect(
14  mapStateToProps,
15  mapDispatchToProps
16)(withStyles(styles)(ToDO));

در نهایت createItem و deleteItem را به ترتیب درون handleSubmit و handleDelete فراخوانی می‌کنیم:

1handleSubmit = event => {
2  // console.log(this.state.item);
3  this.setState({ item: "" });
4  if (this.state.item !== "") {
5    // add the item to the store
6    this.props.createItem(this.state.item);
7  }
8  event.preventDefault();
9};
10
11handleDelete = event => {
12  // delete the item from the store
13  this.props.deleteItem(event.target.value);
14};

سخن پایانی

اگر می‌خواهید کل کد اپلیکیشنی که در این راهنما ساختیم را بررسی کنید، می‌توانید به این ریپازیتوری گیت‌هاب (+) مراجعه کنید. تجربیات خود را در مورد روش استفاده از ریداکس در اپلیکیشن ری‌اکت در بخش نظرات این نوشته با ما و دیگر خوانندگان فرادرس در میان بگذارید.

اگر این مطلب برای شما مفید بوده است، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

==

بر اساس رای ۲ نفر
آیا این مطلب برای شما مفید بود؟
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
wineofbits
نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *