J'essaie de mettre à jour mon ancienne application Todo List React afin qu'elle utilise des crochets, et je ne peux pas comprendre cela pour la vie de moi. setTodos est en train de mettre à jour avec succès l'état au chargement comme indiqué dans les outils de développement React, mais le composant ne se rend pas à nouveau et une liste vide de tâches s'affiche à l'écran. Ce n'est que lorsque j'ajoute un Todo à la liste qu'il est à nouveau rendu et que tous les todos apparaissent. Voici ce que j'ai:
componentDidMount() { dbTodos.get().then((snapshot) => { snapshot.forEach((doc) => { const currentTodo = doc.data(); currentTodo['id'] = doc.id; setState({ ...state, todos: [ ...state.todos, currentTodo ] }); }); }); };
Voici le code que j'ai utilisé avant d'implémenter les hooks:
const App = () => { // Todos are the only state in App const [ todos, setTodos ] = useState([]); // Fetches Todos from Firestore database on load useEffect(() => { const initialState = []; dbTodos.get().then((snapshot) => { snapshot.forEach((doc) => { const currentTodo = doc.data(); currentTodo['id'] = doc.id; initialState.push(currentTodo); }); }); setTodos(initialState); // eslint-disable-next-line }, []); // Add Todo const addTodo = (title) => { const newTodo = { title : title, completed : false }; dbTodos.add(newTodo).then((doc) => { newTodo['id'] = doc.id; setTodos([ ...todos, newTodo ]); }); };
3 Réponses :
Vous devez déplacer vos setTodos dans UseEffect
useEffect(() => { dbTodos.get().then((snapshot) => { const initialState = []; // Also this you can move here snapshot.forEach((doc) => { const currentTodo = doc.data(); currentTodo['id'] = doc.id; initialState.push(currentTodo); }); setTodos(initialState); /// here }); }, []);
Wow, cela a fonctionné comme un charme. Pouvez-vous expliquer la logique derrière cette solution et pourquoi mon code ne fonctionnerait pas?
Bacause dbTodos.get (). Then est appelé async, ce qui signifie que dans votre solution l'appel de commande est 1. Préparez un tableau vide (initialState) 2. Définissez todos avec un tableau de initialState 3. dbTodos.get terminé ajoute éléments dans le tableau (initialState)
Ahh je vois. La partie intéressante cependant est que l'état contenait tout ce qu'il récupérait lors du chargement, ils n'étaient tout simplement pas rendus. On dirait que l'état n'aurait pas du tout dû être changé avec mon code
@JimmyD ouais, mais cet état initial a été mis à jour après setTodos, ce qui signifie que react n'attrape pas ce changement d'état, imaginez-le comme si initialState est juste une référence en mémoire et que cette référence est définie comme nouveau todos par setTodos et que la mémoire est toujours accessible par ce rappel et c'est pourquoi il peut toujours être mis à jour, mais réagit à nouveau lorsque setTodos est appelé maintenant lorsque cette variable change
Ok, c'est tellement plus logique. J'apprécie vraiment l'homme d'aide
Lorsque vous setState dans useEffect, vous devez ajouter setState dans la dépendance. Au lieu de faire cela, utilisez une autre fonction fléchée et appelez-la depuis useEffect.
utilisez le code ci-dessous
const App = () => { // Todos are the only state in App const [ todos, setTodos ] = useState([]); // Fetches Todos from Firestore database on load const fetchData = () => { const initialState = []; dbTodos.get().then((snapshot) => { snapshot.forEach((doc) => { const currentTodo = doc.data(); currentTodo['id'] = doc.id; initialState.push(currentTodo); }); }); setTodos(initialState); } useEffect(() => { fetchData(); }, []); // Add Todo const addTodo = (title) => { const newTodo = { title : title, completed : false }; dbTodos.add(newTodo).then((doc) => { newTodo['id'] = doc.id; setTodos([ ...todos, newTodo ]); }); };
Dans useEffect, vous créez un tableau vide. Faire une demande. définir un tableau vide sur l'état. Lorsque la demande a été satisfaite, vous apportez des modifications au tableau par réf. Par conséquent, vous voyez que votre tableau est dans l'outil de développement et que React ne renvoie pas votre composant.
const App = () => { // Todos are the only state in App const [ todos, setTodos ] = useState([]); // Fetches Todos from Firestore database on load useEffect(() => { dbTodos.get().then((snapshot) => { setTodos(snapshot.map((doc) => ({ id: doc.id, ...doc.data(), }))); }); }, []); // Add Todo const addTodo = (title) => { const newTodo = { title : title, completed : false }; dbTodos.add(newTodo).then((doc) => { newTodo['id'] = doc.id; setTodos([ ...todos, newTodo ]); }); };
Veuillez ajouter le code de JSX ou partout où vous effectuez le rendu