使用useState挂钩的React setState成功更新状态,但未重新渲染组件

时间:2020-03-31 16:54:38

标签: reactjs react-hooks

我正在尝试更新旧的Todo List React应用程序,以便它使用挂钩,并且无法终生解决。 setTodos已成功更新了加载状态,如React开发人员工具所示,但该组件未重新渲染,并且待办事项的空白列表显示在屏幕上。仅当我将待办事项添加到列表中时,它才会重新渲染,并且所有待办事项都显示出来。这就是我所拥有的:

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 ]);
    });
};

这是我在实现钩子之前使用的代码:

componentDidMount() {
    dbTodos.get().then((snapshot) => {
        snapshot.forEach((doc) => {
            const currentTodo = doc.data();
            currentTodo['id'] = doc.id;
            setState({ ...state, todos: [ ...state.todos, currentTodo ] });
        });
    });
};

3 个答案:

答案 0 :(得分:1)

您应在 UseEffect

中移动您的 setTodos
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
    });
}, []);

答案 1 :(得分:0)

在useEffect中使用setState时,必须在依赖项中添加setState。 不用这样做,而使用另一个箭头函数,并从useEffect调用它。

使用下面的代码

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 ]);
    });
};

答案 2 :(得分:0)

在useEffect中,您创建一个空数组。发出请求。将空数组设置为状态。完成请求后,您可以通过ref在数组中进行更改。因此,您会在开发工具中看到数组,并且react不会重新呈现您的组件。

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 ]);
    });
};