MiPiBoy Logo
Back to all articles
DocumentsReactlern

React lern documents 3.

Morteza Aghaei React lern documents 3.

React lern documents 3.

آموزش پروژه محور

  1. یه فایل html پر از محتوا
  2. فایل به JSX منتقل داده شه با یک کامپوننت
  3. پروژه با Tailwind CSS استایل دهی شده بود
  4. برای یادگیری استایل دهی را به روش Styled Components تغییر دادم
  5. و تمام پروژه را به صورت کامپوننت محور تکه تکه کردم

فایل های پروژه:

Todo.jsx

import styled from "styled-components"
import TodoList from "./TodoList"

const MainDiv = styled.div`
  background-color: #fff;
  padding: 12px;
  border-radius: 18px;
  border: solid #7400ba 2px;
`

const Title = styled.h1`
  color: #7400ba;
  font-weight: bold;
`

const AddInput = styled.input`
  width: -webkit-fill-available;
  padding: 12px;
  background-color: #ffffff00;
  border: solid #7400ba 0.5px;
  border-radius: 6px;
  color: #0b0b0b;
`

export default function Todo() {
    return (
        <MainDiv>
            <div>
                <div>
                    <div>
                        <Title>To-Do Project | MiPiboy Academy</Title>
                    </div>
                    <div>
                        <AddInput type='text' placeholder='What needs to be done today?' />
                    </div>
                    <TodoList />
                </div>
            </div>
        </MainDiv>
    )
}

TodoList.jsx

import styled from "styled-components"
import TodoItem from "./Todoitem"

const List = styled.ul`
  margin-block-end: 0.25rem;
  padding: 0;
`


export default function TodoList() {
    return (
        <List>
            <TodoItem />
            <TodoItem />
            <TodoItem />
        </List>
    )
}

TodoItem.jsx

import styled from "styled-components"
import DelTodo from "./DelTodo"
import EditTodo from "./EditTodo"

const ItemDiv = styled.div`
  display: flex;
  flex-direction: row;
  justify-content: space-between;

`
const CheckInput = styled.input.attrs({ type: 'checkbox' })`

`
const Item = styled.li`
  list-style-type: none;
  border-bottom: solid #7400ba 1px;
  padding-block: 1rem;
  
  &:last-child{
    border-bottom: none;
    padding-bottom: 0;
  }
`
const Buttons = styled.button`
  background-color: #ffffff00;
  color: #000;
  display: flex;
  flex-direction: row;
  gap: 5px;
  padding: 5px;
  border: none;
`
const TaskName = styled.p`
  margin-left: 12px;
  color: #0b0b0b;
  display: flex;
  align-items: center;
  width: -webkit-fill-available;
  justify-content: flex-start;

  ${CheckInput}:checked + & {
    text-decoration:line-through;
  }
`
export default function TodoItem() {
    return (
        <Item>
            <ItemDiv>
                <CheckInput />
                <TaskName>Eating breakfast at 7:00</TaskName>
                <Buttons>
                    <EditTodo />
                    <DelTodo />
                </Buttons>
            </ItemDiv>
        </Item>
    )
}

EditTodo.jsx

export default function EditTodo() {
    return (
        <svg
            width="22"
            height="22"
            viewBox="0 0 8 8"
            fill="none"
            xmlns="http://www.w3.org/2000/svg"
        >
            <g opacity="1">
                <path
                    d="M3.66663 0.666626H2.99996C1.33329 0.666626 0.666626 1.33329 0.666626 2.99996V4.99996C0.666626 6.66663 1.33329 7.33329 2.99996 7.33329H4.99996C6.66663 7.33329 7.33329 6.66663 7.33329 4.99996V4.33329"
                    stroke="currentColor"
                    strokeWidth="0.5"
                    strokeLinecap="round"
                    strokeLinejoin="round"
                />
                <path
                    d="M5.34663 1.00663L2.71996 3.6333C2.61996 3.7333 2.51996 3.92996 2.49996 4.0733L2.35663 5.07663C2.30329 5.43996 2.55996 5.6933 2.92329 5.6433L3.92663 5.49996C4.06663 5.47996 4.26329 5.37996 4.36663 5.27996L6.99329 2.6533C7.44663 2.19996 7.65996 1.6733 6.99329 1.00663C6.32663 0.339962 5.79996 0.553295 5.34663 1.00663Z"
                    stroke="currentColor"
                    strokeWidth="0.5"
                    strokeMiterlimit="10"
                    strokeLinecap="round"
                    strokeLinejoin="round"
                />
                <path
                    d="M4.96997 1.3833C5.1933 2.17997 5.81664 2.8033 6.61664 3.02997"
                    stroke="currentColor"
                    strokeWidth="0.5"
                    strokeMiterlimit="10"
                    strokeLinecap="round"
                    strokeLinejoin="round"
                />
            </g>
        </svg>
    )
}

DelTodo.jsx

export default function DelTodo() {
    return (
        <svg
            xmlns="http://www.w3.org/2000/svg"
            width="22"
            height="22"
            viewBox="0 0 16 16"
        >
            <path
                fill="red"
                d="M7 3h2a1 1 0 0 0-2 0M6 3a2 2 0 1 1 4 0h4a.5.5 0 0 1 0 1h-.564l-1.205 8.838A2.5 2.5 0 0 1 9.754 15H6.246a2.5 2.5 0 0 1-2.477-2.162L2.564 4H2a.5.5 0 0 1 0-1zm1 3.5a.5.5 0 0 0-1 0v5a.5.5 0 0 0 1 0zM9.5 6a.5.5 0 0 1 .5.5v5a.5.5 0 0 1-1 0v-5a.5.5 0 0 1 .5-.5m-4.74 6.703A1.5 1.5 0 0 0 6.246 14h3.508a1.5 1.5 0 0 0 1.487-1.297L12.427 4H3.573z"
            />
        </svg>
    )
}

نمایش داینامیک تسک ها

  • انتخاب کامپوننت Todo.jsx برای ساخت آرایه todos به دلیل افزودن تسک با اینپوت موجود در این کامپوننت
  • درست کردن آرایه todos با استفاده از useState
let [todos, setTodos] = useState([
    {name:'Eating breakfast', status:true},
    {name:'Going to gym', status:false},
    {name:'Whaching movie at 10:00', status:true},
])
  • پاس دادن آرایه به کامپوننت TodoList.jsx با استفاده از Props
  • دریافت آرایه {todos} و نمایش لیست با استفاده از متد map
  • پاس هر عضو آرایه به کامپوننت TodoItem.jsx
export default function TodoList( {todos} ) {
    return (
        <List>
            {
                todos.map(
                    (todo) => <TodoItem todo={todo} />
                )
            }
        </List>
    )
}
  • دریافت و استفاده از آرایه {todo} در TodoItem.jsx
export default function TodoItem( {todo} ) {
    return (
        <Item>
            <ItemDiv>
                <CheckInput />
                <TaskName>{todo.name}</TaskName>
                <Buttons>
                    <EditTodo />
                    <DelTodo />
                </Buttons>
            </ItemDiv>
        </Item>
    )
}
  • رفع خطای key با استفاده از index
export default function TodoList({todos}) {
    return (
        <List>
            {
                todos.map(
                    (todo, index) => <TodoItem key={index} todo={todo} />
                )
            }
	        </List>
	    )
	}
  • نمایش ضعیت چک باکس تسک بر اساس {todo.status}
  • افزودن onChange خالی برای رفع خطا
export default function TodoItem({ todo }) {
  return (
    <Item>
      <ItemDiv>
        <CheckInput checked={todo.status} onChange={() => { }} />
        <TaskName >{todo.name}</TaskName>
        <Buttons>
          <EditTodo />
          <DelTodo />
        </Buttons>
      </ItemDiv>
    </Item>
  )
}
  • استفاده از Template Literal برای اختصاص دادن استایل متن خط دار line-through به نام تسک در زمان چک بودن
    • در مثال پروژه با استفاده از Tailwind CSS با توجه به true بودن {todo.status} استایل "line-through" در غیر این صورت " " اضافه میشود.
<p className={` inline-block mt-1 ${todo.status ? "line-through" : ""}`} >{todo.name}</p>
  • اما در مثال ما با توجه به استایل دهی پروژه که به روش Styled Components است، به این صورت نوشتیم:
    • که با استفاده از چک بودن اینپوت CheckInput تغییر میکند که برای چک شدن CheckInput از checked={todo.status} استفاده میکند.
const CheckInput = styled.input.attrs({ type: 'checkbox' })``

const TaskName = styled.p`
  margin-left: 12px;
  color: #0b0b0b;
  display: flex;
  align-items: center;
  width: -webkit-fill-available;
  justify-content: flex-start;

  ${CheckInput}:checked + & {
    text-decoration:line-through;
  }
`

export default function TodoItem({ todo }) {
  return (
    <Item>
      <ItemDiv>
        <CheckInput checked={todo.status} onChange={() => { }} />
        <TaskName >{todo.name}</TaskName>
        <Buttons>
          <EditTodo />
          <DelTodo />
        </Buttons>
      </ItemDiv>
    </Item>
  )
}

قبلی ←

MiPiBoy Blog