Zen Eddin Allaham نشر 27 يونيو أرسل تقرير نشر 27 يونيو كيف يمكنني حفظ البيانات في تخزين المحلي لقد حاولت كثيراً ولم يعمل معي import React,{useState,useRef,useEffect} from "react"; import './App.css'; function App(){ const [todos , setTodos] = useState([]); const inpRef = useRef() const handelButtonClick = () => { const text = inpRef.current.value; const newTodos = {complelted: false ,text} setTodos([...todos, newTodos]) inpRef.current.value = ''; } const handelItemClick = (i) => { const newItem = [...todos]; newItem[i].complelted = !newItem[i].complelted; setTodos(newItem) } const handelDeleteItem = (i) => { const newDelete = [...todos]; newDelete.splice(i,1) setTodos(newDelete) } return( <> <div className="App"> <h2>To Do List</h2> <ul> {todos.map(({text,complelted},i) => { return <div className="item"><li className={complelted ? "done" : ""} onClick={() => handelItemClick(i)}>{text}</li><span onClick={() => handelDeleteItem(i)}>❌</span></div> })} </ul> <input ref={inpRef} placeholder="Enter item..."/> <button onClick={handelButtonClick}>Add</button> </div> </> ) } export default App; 1 اقتباس
0 Mustafa Mahmoud7 نشر 27 يونيو أرسل تقرير نشر 27 يونيو إذا كان هذا التطبيق خاص بأحد دروس الدورة ستجد أسفل فيديو الدرس في نهاية الصفحة صندوق تعليقات كما هنا، أرجو طرح الأسئلة أسفل الدرس وليس هنا في قسم أسئلة البرمجة حيث نطرح الأسئلة العامة الغير متعلقة بمحتوى الدورة أو الدرس، وذلك لمساعدتك بشكل أفضل. لكي يتم حفظ البيانات في التخزين المحلي (localStorage) وتستمر بعد ما يتم إعادة تحميل الصفحة، لابد أن نستخدم localStorage مع useEffect فالمطلوب كالأتي عند تشغيل التطبيق لأول مرة: نقرأ المهام من localStorage. عند تغيير المهام (todos): نقوم بتحديث localStorage ونضيف المهام المحدثة به. لهذا الأمر عليك بإضافة التالي إلى الكود الخاص بك // قراءة البيانات من التخزين المحلي عند تحميل الصفحة أول مرة useEffect(() => { const storedTodos = localStorage.getItem("todos"); if (storedTodos) { setTodos(JSON.parse(storedTodos)); } }, []); // حفظ المهام في التخزين المحلي عند كل تغيير في القائمة useEffect(() => { localStorage.setItem("todos", JSON.stringify(todos)); }, [todos]); في الـ useEffect الأولي يتم التالي هذا الكود بداخل useEffect يعمل مرة واحدة فقط عند تحميل المكون APP بسبب [] في النهاية. يقوم بالبحث في localStorage عن شيء محفوظ باسم المفتاح todos. إذا وجده نحوله من نص إلى مصفوفة باستخدام ()JSON.parse ثم نخزنها داخل todos باستخدام ()setTodos. في الـ useEffect الثانية يتم التالي هذا الكود بداخل useEffect يعمل في كل مرة تتغير فيها المهام todos بسبب [todos]. يقوم بتحويل المهام إلى نص باستخدام ()JSON.stringify ثم يقوم بحفظ هذا النص داخل localStorage باسم المفتاح todos. اقتباس
0 Zen Eddin Allaham نشر 27 يونيو الكاتب أرسل تقرير نشر 27 يونيو الكود الذي ارسلته لي الخاص بتخزين المحلي توجد به اخطاء 1 اقتباس
0 Mustafa Mahmoud7 نشر 27 يونيو أرسل تقرير نشر 27 يونيو خطأ غريب حيث قمت باختبار الكود عدة مرات سواء بإعادة التحميل للتطبيق أو الإضافة أو الحذف ولا يظهر هذا الخطأ لدي. أرجو أيضا تفريغ الـ localStorage من البيانات الموجودة به ربما هناك بيانات قديمة مخزنة به تحت المفتاح todos أيضا. من الممكن أن يكون هناك إضافة لديك في المتصفح تؤدي إلى ذلك الخطأ لذا يرجى تشغيل التطبيق في المتصفح الخفي وإعادة المحاولة. وأرجو أيضا استبدال هذا السطر return <div className="item"><li className={complelted ? "done" : ""} onClick={() => handelItemClick(i)}>{text}</li><span onClick={() => handelDeleteItem(i)}>❌</span></div> بالتالي return ( <div className="item" key={i}> <li className={complelted ? "done" : ""} onClick={() => handelItemClick(i)} > {text} </li> <span onClick={() => handelDeleteItem(i)}>❌</span> </div> ); قمنا بإضافة الـ key للـ div وهو مهم عند العمل مع map في react. من المفترض ألا تظهر معك أي أخطاء في الـ console أو تحذيرات ويعمل معك التطبيق بدون مشكلة. اقتباس
0 Mustafa Mahmoud7 نشر 27 يونيو أرسل تقرير نشر 27 يونيو هذا الخطأ يخبرك أنك تقوم بمحاول الوصول للثابت todos في سطر 15 وهذا الثابت قبل ما يتم تعريفه أو تهيئته (initialization). لذلك يرجى نقل عملية استخدام الـ todos ومحاولة الوصول لقيمته أسفل عملية التعريف له. فمثلا في هذا الكود const handelButtonClick = () => { const text = inpRef.current.value; const newTodos = {complelted: false ,text} setTodos([...todos, newTodos]) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ inpRef.current.value = ''; } const [todos , setTodos] = useState([]); ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ هذا الكود ليس بالظبط في أكوادك التي أرسلتها سابقا فقط لبيان كيف يمكن أن يحدث هذا الخطأ سيظهر معك هذا الخطأ Cannot access 'todos' before initialization لأنك بتحاول تستخدم حاجة لسه ما اتعرفتش. وتصحيح هذا الكود يكون كالأتي const [todos , setTodos] = useState([]); const handelButtonClick = () => { const text = inpRef.current.value; const newTodos = {complelted: false ,text} setTodos([...todos, newTodos]) inpRef.current.value = ''; } لذلك قم بالبحث عن السطر الذي قم فيه بتعريف todos وانقله قبل السطر رقم 15 والتجربة مرة أخرى. اقتباس
0 Zen Eddin Allaham نشر 27 يونيو الكاتب أرسل تقرير نشر 27 يونيو لقد رفعت الخطافات الى الاعلى وظهر اخطاء اكثر import React,{useState,useRef, useEffect} from "react"; import './App.css' import logo from './assets/react.svg' function App(){ const [todos , setTodos] = useState([]); const inpRef = useRef(); /// قراءة البيانات من التخزين المحلي عند تحميل الصفحة أول مرة useEffect(() => { const storedTodos = localStorage.getItem("todos"); if (storedTodos) { setTodos(JSON.parse(storedTodos)); } }, []); // حفظ المهام في التخزين المحلي عند كل تغيير في القائمة useEffect(() => { localStorage.setItem("todos", JSON.stringify(todos)); }, [todos]); const handelButtonClick = () => { const text = inpRef.current.value; const newTodos = {compiled: false, text} inpRef.current.value = ''; setTodos([...todos,newTodos]) } const handelItemClick = (i) => { const newItem = [...todos]; newItem[i].compiled = !newItem[i].compiled; setTodos(newItem) } const handelDeleteClick = (i) => { const newDelete = [...todos]; newDelete.splice(i,1) setTodos(newDelete); } return( <> <img src={logo} alt="" /> <div className="App"> <h2>To Do List</h2> <ul> {todos.map(({text,compiled}, i) => { return <div className="item"><li key={i} className={compiled ? 'done' : ''} onClick={() => handelItemClick(i)}>{text}</li><span onClick={() => handelDeleteClick(i)}>❌</span></div> })} </ul> <input ref={inpRef} placeholder="Enter item..."/> <button onClick={handelButtonClick}>Add</button> </div> </> ) } export default App; 1 اقتباس
0 Mustafa Suleiman نشر 27 يونيو أرسل تقرير نشر 27 يونيو بتاريخ 16 دقائق مضت قال Hxfhf Ucicic: لقد رفعت الخطافات الى الاعلى وظهر اخطاء اكثر import React,{useState,useRef, useEffect} from "react"; import './App.css' import logo from './assets/react.svg' function App(){ const [todos , setTodos] = useState([]); const inpRef = useRef(); /// قراءة البيانات من التخزين المحلي عند تحميل الصفحة أول مرة useEffect(() => { const storedTodos = localStorage.getItem("todos"); if (storedTodos) { setTodos(JSON.parse(storedTodos)); } }, []); // حفظ المهام في التخزين المحلي عند كل تغيير في القائمة useEffect(() => { localStorage.setItem("todos", JSON.stringify(todos)); }, [todos]); const handelButtonClick = () => { const text = inpRef.current.value; const newTodos = {compiled: false, text} inpRef.current.value = ''; setTodos([...todos,newTodos]) } const handelItemClick = (i) => { const newItem = [...todos]; newItem[i].compiled = !newItem[i].compiled; setTodos(newItem) } const handelDeleteClick = (i) => { const newDelete = [...todos]; newDelete.splice(i,1) setTodos(newDelete); } return( <> <img src={logo} alt="" /> <div className="App"> <h2>To Do List</h2> <ul> {todos.map(({text,compiled}, i) => { return <div className="item"><li key={i} className={compiled ? 'done' : ''} onClick={() => handelItemClick(i)}>{text}</li><span onClick={() => handelDeleteClick(i)}>❌</span></div> })} </ul> <input ref={inpRef} placeholder="Enter item..."/> <button onClick={handelButtonClick}>Add</button> </div> </> ) } export default App; المشكلة في دالة الدالة JSON.parse()، فالنص الذي تستقبله ليس بصيغة JSON صحيحة، أي هنا: setTodos(JSON.parse(storedTodos)); غالبًا قمت بتخزين بيانات غير صحيحة في التخزين المحلي من قبل، حيث يوجد دالة في Local Storage بدلاً من قائمة المهام. اضغط على F12 ثم توجه إلى تبويب Application في أدوات المطور، ثم اختر Local Storage وستجد التخزين الخاص بعنوان localhost:3000 مثلاً، فاضغط عليه ثم قم بالحذف بالضغط على الزر التالي: بعد ذلك أعد تحديث الصفحة وقم بحفظ البيانات والتجربة من جديد. اقتباس
0 Zen Eddin Allaham نشر 27 يونيو الكاتب أرسل تقرير نشر 27 يونيو قمت بحذف بيانات ومازالت المشكلة موجودة 1 اقتباس
0 Mustafa Suleiman نشر 27 يونيو أرسل تقرير نشر 27 يونيو بتاريخ الآن قال Hxfhf Ucicic: قمت بحذف بيانات ومازالت المشكلة موجودة هل قمت بتحديث الصفحة؟ عامًة تفقد ما هي البيانات التي يتم جلبها من التخزين من خلال الكونسول كالتالي: useEffect(() => { const storedTodos = localStorage.getItem("todos"); console.log("القيمة المخزنة التي تمت قراءتها:", storedTodos); //هنا if (storedTodos) { setTodos(JSON.parse(storedTodos)); } }, []); وتفقد المشكلة، ثم تستطيع إرفاق مجلد المشروع لتفقده. اقتباس
0 Zen Eddin Allaham نشر 28 يونيو الكاتب أرسل تقرير نشر 28 يونيو المشكلة مستمرة To-Do-List.zip 1 اقتباس
0 محمد_عاطف نشر 28 يونيو أرسل تقرير نشر 28 يونيو بتاريخ منذ ساعة مضت قال Hxfhf Ucicic: المشكلة مستمرة To-Do-List.zip 31.2 kB · 2 تنزيلات المشروع يعمل دون أى مشكلة لقد قمت بتجربته ولا تحدث به أى أخطاء. ولكن توجد مشكلة في المنطق حيث عند تحديث الصفحة يتم حذف جميع المهام لتصبح قائمة المهام فارغة في التخزين المحلي. والسبب هو إستخدامك لإثنين من useEffect حيث ال useEffect الثانية يتم تنفيذها في البداية والتي يكون فيها قيمة todos بمصفوفة فارغة . وإليك الكود التالي الصحيح للحل : import React, { useState, useRef, useEffect } from "react"; import './App.css' import logo from './assets/react.svg' function App() { const [todos, setTodos] = useState([]); const inpRef = useRef(); /// قراءة البيانات من التخزين المحلي عند تحميل الصفحة أول مرة useEffect(() => { const storedTodos = localStorage.getItem("todos",); if (storedTodos) { setTodos(JSON.parse(storedTodos)); } }, []); // حفظ المهام في التخزين المحلي عند كل تغيير في القائمة // useEffect(() => { // localStorage.setItem("todos", JSON.stringify(todos)); // }, [todos]); const handelButtonClick = () => { const text = inpRef.current.value; const newTodos = { compiled: false, text } inpRef.current.value = ''; setTodos([...todos, newTodos]) localStorage.setItem("todos", JSON.stringify([...todos, newTodos])); } const handelItemClick = (i) => { const newItem = [...todos]; newItem[i].compiled = !newItem[i].compiled; setTodos(newItem) localStorage.setItem("todos", JSON.stringify(newItem)); } const handelDeleteClick = (i) => { const newDelete = [...todos]; newDelete.splice(i, 1) setTodos(newDelete); localStorage.setItem("todos", JSON.stringify(newDelete)); } return ( <> <img src={logo} alt="" /> <div className="App"> <h2>To Do List</h2> <ul> {todos.map(({ text, compiled }, i) => { return <div className="item"><li key={i} className={compiled ? 'done' : ''} onClick={() => handelItemClick(i)}>{text}</li><span onClick={() => handelDeleteClick(i)}>❌</span></div> })} </ul> <input ref={inpRef} placeholder="Enter item..." /> <button onClick={handelButtonClick}>Add</button> </div> </> ) } export default App; اقتباس
0 Zen Eddin Allaham نشر 28 يونيو الكاتب أرسل تقرير نشر 28 يونيو المشكلة مستمرة وحتى اني قمت بحذف بيانات تخزين المحلي 1 اقتباس
0 محمد_عاطف نشر 28 يونيو أرسل تقرير نشر 28 يونيو بتاريخ 43 دقائق مضت قال Hxfhf Ucicic: المشكلة مستمرة وحتى اني قمت بحذف بيانات تخزين المحلي لقد لاحظت الصورة السابقة التي أرفتها وهي تظهر أنك قد قمت بحذف ال session storage ولكن الصحيح هو local storage هنا : اقتباس
السؤال
Zen Eddin Allaham
كيف يمكنني حفظ البيانات في تخزين المحلي
لقد حاولت كثيراً ولم يعمل معي
14 أجوبة على هذا السؤال
Recommended Posts
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.