Todolist with useState() | Xây dựng ứng dụng todolist | React hooks

Поділитися
Вставка
  • Опубліковано 11 жов 2021
  • 👉 Xem Lộ Trình Học: fullstack.edu.vn/learning-paths
    👉 Đăng Ký Học Offline Tại F8: short.f8team.dev/dang-ky-hoc-...
    Video này chúng ta sẽ tiếp tục tìm hiểu về Todolist with useState() | Xây dựng ứng dụng todolist | React hooks
    Trong bài này chúng ta sẽ đi làm thêm 1 ví dụ Todolist rồi bài sau học sang useEffect() hook nhé anh em.
    #hoclaptrinh #hoclaptrinhmienphi #javascript #reactjs #frontend #backend #devops #f8
    -------
    ☻ Phần mềm sử dụng trong video:
    Công cụ dịch Tiếng Anh: bit.ly/2Wsuhet
    Công cụ đo đạc giao diện web: s.net.vn/D8kL
    Công cụ viết CV xin việc chuyên nghiệp: mycv.vn
    --------------
    ☻ Khóa học lập trình web MIỄN PHÍ:
    Kiến thức nhập môn: fullstack.edu.vn/courses/less...
    Xây dựng giao diện với HTML, CSS: fullstack.edu.vn/courses/html...
    Xây dựng web responsive: fullstack.edu.vn/courses/resp...
    Lập trình Javascript cơ bản: fullstack.edu.vn/courses/java...
    Lập trình Javascript nâng cao: fullstack.edu.vn/courses/java...
    Làm việc với Terminal & Ubuntu: fullstack.edu.vn/courses/wind...
    Xây Dựng Website với ReactJS: fullstack.edu.vn/courses/reactjs
    Xây dựng web với Node & Express: fullstack.edu.vn/courses/nodejs
    HTML, CSS tips: fullstack.edu.vn/courses/html...
    Ứng dụng cảnh báo khi sờ lên mặt: fullstack.edu.vn/courses/tool...
    Xem thêm tại: fullstack.edu.vn/courses
    -------------------------------------
    F8 Official
    (c) Sơn Đặng
    Website: fullstack.edu.vn
    Facebook cá nhân: / sondnf8
    Nhóm Học Lập Trình Web: / f8official
    Email: contact@fullstack.edu.vn
    © Bản quyền thuộc về Channel F8 Official ☞ Do not Reup
    © Nghiêm cấm sử dụng video nhằm mục đích thương mại dưới mọi hình thức.
  • Наука та технологія

КОМЕНТАРІ • 98

  • @F8VNOfficial
    @F8VNOfficial  2 роки тому +21

    Trong bài này chúng ta sẽ đi làm thêm 1 ví dụ Todolist rồi bài sau học sang useEffect() hook nhé anh em. Bài tập: Anh em xây dựng chức năng xóa cho Todolist nữa nhé 😍😍

    • @haitri1206
      @haitri1206 2 роки тому +1

      anh ơi anh chữa bài chức năng xoá được ko anh

  • @yenka3205
    @yenka3205 2 роки тому +12

    Đã học và hiểu. Hay quá thầy Sơn ơi
    import { useState } from "react";
    const JOB_KEY = "JOB_LIST";
    function App() {
    const [job, setJob] = useState("");
    const [jobList, setJobList] = useState(() => {
    const storageJobList = JSON.parse(localStorage.getItem(JOB_KEY));
    return storageJobList ?? [];
    });
    const handleAddJob = () => {
    if (job === "") {
    return;
    }
    setJobList((prevState) => {
    const newJobList = [...prevState, job];
    const jsonJobList = JSON.stringify(newJobList);
    localStorage.setItem(JOB_KEY, jsonJobList);
    return newJobList;
    });
    setJob("");
    };
    return (


    setJob(e.target.value)} />
    Add

    {jobList.map((job, index) => (
    {job}
    ))}



    );
    }
    export default App;

  • @tonalone2912
    @tonalone2912 2 роки тому

    Tuyệt vời!
    Thanks anh!

  • @heofa7733
    @heofa7733 2 роки тому +2

    Chức năng xóa: thêm 1 button trong thẻ li rồi gán hàm removejob bên dưới vào sự kiện onClick và truyền job vào là xong
    //button trong thẻ li
    { removeJob(job) }}>Xóa
    //hàm removeJob
    var removeJob = function (job) {
    setJobs((prev) => {
    var newArray = prev.filter((item) => item !== job);
    var jsonStringArray = JSON.stringify(newArray);
    localStorage.setItem('TODO_APP', jsonStringArray);
    return newArray;
    })
    }

  • @hoaimiqng
    @hoaimiqng 2 роки тому +1

    Hay luôn anh ạ

  •  2 роки тому

    Chào a buổi tối vui vẻ

  • @nguyenthanhtung3625
    @nguyenthanhtung3625 2 роки тому +2

    Hay quá anh 2 =))

  • @tuanthamlam2274
    @tuanthamlam2274 2 роки тому +6

    chỗ setJobs(prev => [...prev, job]) thiếu điều kiện rồi, nếu mình không nhập gì vào thì ấn add sẽ hiện ra khoảng trắng.

  • @ucthangtruong8317
    @ucthangtruong8317 2 роки тому +1

    dạo này bận việc học nên ít xem video của a

  • @tripham8864
    @tripham8864 2 роки тому +3

    E đã học qa nhìu hook nhưng cái useEffect hơi khó hiểu ở sau function phải có [ ]. Có khi còn phải thêm biến [variable]. Hóng a nói rõ về phần này khi ra video về useEffect ạ. E cảm ơn

  • @phamquangthieu00
    @phamquangthieu00 2 роки тому

    Mong khóa Node sắp tới của anh Sơn sẽ là NestJS ạ

  • @xuanthanhtran9728
    @xuanthanhtran9728 2 роки тому +2

    fan cứng cmt đầu =)

  • @loiloi2895
    @loiloi2895 2 роки тому

    quá xịn

  • @QuanLe-zc9px
    @QuanLe-zc9px 2 роки тому +1

    anh ơi anh làm về ví dụ input upload image mà có tập hợp 3 cái input cho 3 cái ảnh
    đi ạ

  • @htl_tintin651
    @htl_tintin651 9 місяців тому

    video đỉnh thật f8

  • @LeVanMinh-ig5qe
    @LeVanMinh-ig5qe Рік тому

    hay

  • @DavidJames535
    @DavidJames535 2 роки тому

    yêu nhà cái F8 nhiều :)))))

  • @bonnAka
    @bonnAka Рік тому

    anh ơi anh có thể giải thích giúp em ở 2 dòng sử dụng useState khi mà mình thay đổi lại vị trí cho dòng đó thì thứ tự thực thi setState nó lại khác nhau không anh ?

  • @BaoTran-ii6pc
    @BaoTran-ii6pc 2 роки тому +5

    Thầy Sơn đang lên từng bước thầy ấy sẽ làm sau khi làm xong video này, đó là
    Bước 1: Quet Nha
    Bước 2: Lau Nha
    Bước 3: Giat Quan Ao
    😂😂😂

    • @ankhanhbui7606
      @ankhanhbui7606 Рік тому

      có quét nhà mà chưa có lau nhà này -))) thầy cuteee

  • @thinhquang519
    @thinhquang519 2 роки тому +1

    khi add nó chưa thêm luôn vào mang thi khi làm phần xóa không thể lấy index ra a ạ...mong a chỉ em cách làm ạ

  • @baao2748
    @baao2748 Рік тому

    từ phút 13 trở đi tua lại 10 lần mới hiểu hết

  • @namhv967
    @namhv967 Рік тому

    Mọi người cho mình hỏi sao 13:52 console.log(storageJobs) (line 16) chỉ ra 3 phần tử sau khi click Add vậy, đúng ra phải là 4 phần tử chứ (vì lúc này trong localStorage là 4 phần tử). Thanks all.

  • @quoctuan6304
    @quoctuan6304 2 роки тому +1

    Cho em xin info cái ghê của anh được không ạ :))

  • @zomodiscovery4658
    @zomodiscovery4658 2 роки тому +1

    A Sơn cho e hỏi khi trong cùng 1 function a setJob(new value) va setJobs(new value) thi luc nay component se bi re-render lai 2 lan hay sao anh.Và sau khi kết thúc function đó nó mới set lai state, thi luc nay 2 cai state đó thay đổi nên nó re-render lại 2 lần hay chỉ 1 lần thôi ạ

    • @F8VNOfficial
      @F8VNOfficial  2 роки тому +2

      Trong React < v18 thì setState nhiều lần (ko trong async/promise) thì chỉ re-render 1 lần, trong async/promise thì re-render ứng với số lần setState. React v18 thì cả 2 trường hợp đều setState 1 lần.

  • @BlueMoon-ru3wg
    @BlueMoon-ru3wg Рік тому

    lúc storageJobs không có nó lấy [ ] thì f5 sẽ mất hết dữ liệu phải ko mn. vì useState chỉ chạy một lần 😐.

  • @BlueMoon-ru3wg
    @BlueMoon-ru3wg Рік тому

    ủa cái useState chỉ chạy 1 lần nhưng tại sao lúc in ra list job ấy sao lại lấy đc giá trị mới nhất của useState gán lại vào job trong khi nó lấy ở json vậy ạ

  • @ledinhthai69
    @ledinhthai69 Рік тому +1

    Hình như có sự nhầm lẫn thì phải. Ngay tại đoạn cuối của video, để tránh phải lập lại code bạn Sơn (xin lỗi chỗ này nhé, vì mình già lắm rồi, mình thích học thôi, nên gọi là bạn - mà đúng ra là thầy Sơn cũng được.) bạn Sơn có đem JSON.parse vào trong useState và dùng function ở chỗ này. Nếu đã có dữ liệu trong localStorage rồi thì nó ko bị gì. Còn nếu không có dữ liệu thì cái hàm đó nó return ra (null) và bị lỗi ngay. Chỗ này thì chỉ nên đem đoạn code sau vào useState. Câu lệnh nên viết như sau:
    const [jobs, setJobs] = useState(JSON.parse(localStorage.getItem('jobs')) ?? [ ])
    thì sẽ ko bị lỗi, vì khi gặp null nó sẽ chọn mảng rỗng. Xin cảm ơn rất nhiều

    • @buukhanhong40
      @buukhanhong40 Рік тому

      Phải truyền kiểu callback mới đúng a

    • @Misskieutra
      @Misskieutra Рік тому

      const storageJobs = JSON.parse(localStorage.getItem("jobs")) return storageJobs ?? []. E thấy return vậy cg đúng ạ.

    • @nghiahoang9201
      @nghiahoang9201 Рік тому

      @@Misskieutra function App() {
      const [job, setJob] = useState('');
      const [jobs, setJobs] = useState(getStorage ?? []);
      function getStorage() {
      const storageJobs = JSON.parse(localStorage.getItem('jobs'));

      return storageJobs;
      }

  • @tw7716
    @tw7716 2 роки тому +2

    14:43 return storageJob ?? [ ]

  • @vankhanhinfo
    @vankhanhinfo 2 роки тому +2

    Hôm nay mới học tới bài này, rất dễ hiểu và hữu ích, thanks a Sơn nhé, có bổ sung thêm là phần set useState job thì khi return cần thêm toán tử nullish storageJob ?? []

    • @F8VNOfficial
      @F8VNOfficial  2 роки тому

      Cảm ơn em nha, lúc anh sửa lại xong quên mất chỗ đó 😢

  • @loiloi2895
    @loiloi2895 2 роки тому

    hi idol

  • @upagency7439
    @upagency7439 2 роки тому +2

    a sơn ơi, a cho e hỏi 1 vấn dề nhỏ, useState(initVAlue), vậy khi mỗi lần mình setState thì state này sẽ được lưu ở đâu v a

    • @Mossad84
      @Mossad84 Рік тому +1

      setState thì truyền về State

  • @quangaonguyen7898
    @quangaonguyen7898 2 роки тому +1

    có ai làm update todolist không ạ cho miình xem code với

  • @inhxuanhanh4314
    @inhxuanhanh4314 2 роки тому +1

    Cho e hỏi mỗi khi change input thì sẽ component sẽ re-render 1 lần, có cách nào chỉ render 1 lần k a

    • @zomodiscovery4658
      @zomodiscovery4658 2 роки тому

      render 1 lan thi lam sao no cap nhat duoc gia tri moi ban

  • @Vanang-bf1jp
    @Vanang-bf1jp 2 роки тому +1

    anh ơi lúc handleSubmit thì mình nên kiểm tra xem có job ko rồi mới set lại để nó ko render ra li rỗng thì ok hơn ạ 😄

    • @F8VNOfficial
      @F8VNOfficial  2 роки тому +1

      Ví dụ thôi mà em. Còn làm thật thì đâu chỉ có case em nói. Cảm ơn em nhé.

    • @Vanang-bf1jp
      @Vanang-bf1jp 2 роки тому +1

      @@F8VNOfficial 😂vâng ,cảm ơn anh vì những khóa học tuyệt vời này ạ ❤❤

  • @hungminhphan6095
    @hungminhphan6095 Рік тому

    Chỗ giá trị khởi tạo list sao lại dùng && mà ko dùng || v a

  • @hunghahuy9318
    @hunghahuy9318 2 роки тому +3

    em nhận ra đoạn cuối cùng video có vấn đề. thay vì là return StorageJobs thì mình nên ghi là return StorageJobs === null ? [] : StorageJobs;

    • @huonglexuan9697
      @huonglexuan9697 2 роки тому +1

      tại anh Sơn quên đó bạn, nhưng theo mình đúng hơn phải là return storageJobs ?? [ ] chứ như bạn còn thiếu trường hợp undefined

    • @hunghahuy9318
      @hunghahuy9318 2 роки тому +1

      @@huonglexuan9697 bạn bị nhầm rồi. đang set mảng rỗng là giá trị khởi tạo mà . với Mình cũng hoàn thành khóa react bên udemy rồi ,qua f8 xem cho vui thôi

  • @sangnguyenquang7208
    @sangnguyenquang7208 Рік тому

    Ở cuối video đoạn return ra storageJobs vẫn phải thêm ?? [] chứ anh, không nó lại lỗi khi xóa JSON trong localstorage

    • @F8VNOfficial
      @F8VNOfficial  Рік тому

      Đúng rồi bạn ơi. Mình thiếu sót chỗ này

  • @phungtruongdinhquan7765
    @phungtruongdinhquan7765 2 роки тому +1

    Làm sao để nâng cao tư duy viết code nhỉ. Đôi khi ko có ai hướng dẫn thì e mù luôn :v

  • @thinhnguyen9290
    @thinhnguyen9290 Рік тому +1

    cuối video a truyền cái callback vào useState() mà đoạn return đó chưa check đc đoạn storageJobs = null thì lúc load trang mà chưa có 'jobs' trong storage thì ăn lỗi ròi 😢

    • @F8VNOfficial
      @F8VNOfficial  Рік тому +1

      Đúng rồi, anh thiết sót đó. Em sửa lại giúp anh nha

  • @baotrinh3716
    @baotrinh3716 2 роки тому

    Mọi người cho hỏi phút thứ 4:10 dòng 18
    setJobs(prev => [...prev, job]);
    khác gì với setJobs([...jobs, job])
    Cám ơn Anh Sơn và các bạn

    • @zomodiscovery4658
      @zomodiscovery4658 2 роки тому +1

      k có khác gì, chỉ là 1 cách viết khác thôi nha bạn...

  • @sonlengoc948
    @sonlengoc948 Рік тому

    khi gắn value của input là job, thì nó warning, làm sao fix warning này vậy anh
    "A component is changing an uncontrolled input to be controlled"

    • @huutuongphan9039
      @huutuongphan9039 Рік тому

      khai báo state mặc định lúc đầu là chuỗi nhé, nếu chỉ () thôi thì nó undefined -> lỗi ấy

  • @NamLe-sl4qy
    @NamLe-sl4qy Рік тому

    6:00 chưa dùng được jobs ngay sau khi setJobs

  • @nguyenquocan8949
    @nguyenquocan8949 2 роки тому +1

    giữa context api với redux thì mình nên chọn cái nào anh, hay học cả hai nhỉ

  • @bachduong4236
    @bachduong4236 Рік тому +1

    thiếu check null ở init state ở cuối video a ơi .

    • @levanduy1406
      @levanduy1406 Рік тому

      return storageJobList ?? [];
      Cảm ơn bạn đã nhắc.

  • @oanduyman4394
    @oanduyman4394 2 роки тому +1

    Khi mình không nhập dữ liệu mà mình nhấn vào Add thì nó vẫn render ra thẻ với giá trị rỗng a.

    • @F8VNOfficial
      @F8VNOfficial  2 роки тому

      Mấy cái liên quan anh em tự xử lý thêm nhé. Vì mình đang học useState và todo chỉ lấy ra làm ví dụ thôi mà em

    • @oanduyman4394
      @oanduyman4394 2 роки тому

      @@F8VNOfficial dạ a.

  • @BDCPT-inhThiHuongThao
    @BDCPT-inhThiHuongThao 2 роки тому +1

    Mình có câu hỏi: liệu có thể dùng setState(jobs.push(job)); có được không?

    • @F8VNOfficial
      @F8VNOfficial  2 роки тому +1

      Ko bạn nhé. Quay trở lại bài học về method push() bạn sẽ biết nó trả về độ dài mới của mảng. Vd mảng có 3 phần tử rồi push thêm 1 phần từ length sẽ là 4. Như vậy setState sẽ lấy 4 làm state.

    • @thanhtung1502
      @thanhtung1502 Рік тому

      ​@@F8VNOfficial Mình cũng thắc mắc. Sao không gọi push() trực tiếp trong sự kiện click?
      Thay vì định nghĩa lại hàm setJobs để cập nhật state cho jobs thì mình dùng push()/unshift() để cập nhật state thì sao ạ???
      function TodoApp() {
      const [jobs, setJobs] = useState([]);
      const [input, setInput] = useState("");
      function handleClick(e) {
      jobs.unshift(input);
      setInput("");
      }
      return (

      React Todo App
      setInput(e.target.value)} />
      Add

      {jobs.map((job, index) => (
      {job}
      ))}


      );
      }

  • @baohoang1371
    @baohoang1371 Рік тому

    14:00
    return storageJobList ?? [];

  • @sonlengoc948
    @sonlengoc948 Рік тому

    12:10 em dùng toán tử || vẫn hoạt động được đúng không anh

    • @F8VNOfficial
      @F8VNOfficial  Рік тому +1

      Trường hợp này thì cũng tương tự nhau nha em. Dùng đc nha em.

  • @user-ek5uc8jy6u
    @user-ek5uc8jy6u 5 місяців тому

    Tại sao chỗ consle.log của e lại in ra 2 lần vậy ak

    • @F8VNOfficial
      @F8VNOfficial  5 місяців тому

      Ở index.js em xem có đang sùng comp StrictMode thì em comment nó lại nha

  • @ngthuongnguyen9804
    @ngthuongnguyen9804 2 роки тому +1

    a ơi cho e hỏi 'prev' là từ khóa hay sao anh?

    • @ngthuongnguyen9804
      @ngthuongnguyen9804 2 роки тому

      ý e 'prev' là từ khóa hay biến ạ

    • @F8VNOfficial
      @F8VNOfficial  2 роки тому +1

      Biến mình tự đặt tên thôi em nhé, trong video thì nó là tên tham số của hàm thôi em nhé

    • @ngthuongnguyen9804
      @ngthuongnguyen9804 2 роки тому

      @@F8VNOfficial cảm ơn anh

  • @khannguyenhoang547
    @khannguyenhoang547 2 роки тому +1

    6:02 thực sự là chưa hiểu, ai giúp mình với 😞

    • @tuannguyenhuu964
      @tuannguyenhuu964 2 роки тому

      xem kĩ lại video trước của a Sơn á bạn

  • @tandang7191
    @tandang7191 2 роки тому

    cmt nhì thôi :3

  • @lequan4689
    @lequan4689 2 роки тому

    ngoài Quét nhà ra anh không biết làm gì nữa à :))

  • @hongsonvu3717
    @hongsonvu3717 2 роки тому

    cho mình hỏi toán tử ?? tên là gì vậy? mình không nghe rõ :))

    • @F8VNOfficial
      @F8VNOfficial  2 роки тому +2

      Là "nullish" nha bạn, sorry bạn mình phát âm thiếu "sh" ở cuối

    • @hongsonvu3717
      @hongsonvu3717 2 роки тому

      @@F8VNOfficial cảm ơn Sơn nhé, mỗi video bài giảng của bạn thật sự rất chất lượng, rất dễ hiểu và hữu ích.

  • @KH-dr8ei
    @KH-dr8ei 2 роки тому +1

    bt mình làm hơi máy móc, bạn nào có cách tối ưu không cho mình xin ý kiến =))
    const handleDel = (index) => {
    setJobs((prev) => {
    prev = jobs.filter((job) => job !== jobs[index]);
    const jsonJobs = JSON.stringify(prev);
    localStorage.setItem("jobs", jsonJobs);
    return prev;
    });
    };
    const handleClearAll = () => {
    setJobs((prev) => {
    prev = jobs.splice(0, jobs.length);
    const jsonJobs = JSON.stringify(prev);
    localStorage.setItem("jobs", jsonJobs)
    return prev;
    });
    };
    return (

    setJob(e.target.value)} />
    Add
    Clear All

    {jobs.map((job, index) => (

    {job}
    handleDel(index)}>
    X


    ))}


    );

    • @tranquoctoan1361
      @tranquoctoan1361 2 роки тому

      Mình có đoạn code này, bạn có thể tham khảo
      const [job, setJob] = useState('')
      const [jobs, setJobs] = useState(() => {
      const storageJobs = JSON.parse(localStorage.getItem('jobs'))
      return storageJobs ?? []
      })
      const saveLocalStorageJobs = (data) => {
      const jobsJSON = JSON.stringify(data)
      localStorage.setItem('jobs', jobsJSON)
      }
      const handleRemove = (indexValue) => {
      setJobs(prev => {
      const newJobs = prev.filter((item, index) => index !== indexValue)
      saveLocalStorageJobs(newJobs)
      return newJobs
      })
      }
      const handleRemoveAll = () => {
      setJobs(prev => {
      const emptyArray = []
      saveLocalStorageJobs(emptyArray )
      return emptyArray
      })
      }
      const handleClick = () => {
      setJobs(prev => {
      const stateJobs = [...prev, job]
      //Save jobs to localStorage
      saveLocalStorageJobs(stateJobs)
      return stateJobs
      })
      setJob('')
      }
      return (

      setJob(e.target.value)}
      />
      Add

      Remove All

      {jobs.map((job, index) =>

      {job}
      handleRemove(index)}
      >
      Remove


      )}


      )

    • @baobui1009
      @baobui1009 Рік тому +1

      setJobs((prev) => {
      prev = jobs.filter((job) => job !== jobs[index]);
      const jsonJobs = JSON.stringify(prev);
      localStorage.setItem("jobs", jsonJobs);
      return prev;
      });
      };
      đối với cái này b nên so sánh vs 2 id nha b so sánh như v sẽ xóa 2 phần tử nếu trùng tên đó vd bạn có 2 Task 1 khi b click sẽ xóa 2 cái Task 1

  • @Misskieutra
    @Misskieutra Рік тому

    cho Delete:
    const deleteList = ()=>{
    localStorage.clear();
    setJobs([])
    }

  • @B8Official
    @B8Official 2 роки тому +1

    Good job