繁体   English   中英

如何根据变量值使 useEffect react 钩子重新渲染?

[英]How can I make useEffect react hook rerender based on a variable value?

所以我得到了这个组件:

export default function () {
    const [todos, setTodos] = useState([]);


    useEffect(() => {
        function populateTodos () {
            axios.get(`http://localhost:8000/api/all-todos`)
                .then(res => setTodos(res.data))
                .catch(err => console.log(err));
        }

        populateTodos();
    }, []);

    console.log(todos);

    return (
        <div>
            ...
        </div>
    );
}

我正在使用useEffect钩子从数据库中获取所有useEffect ,并且工作正常。 问题是我不知道如何使用useEffect在我对 todos 数组进行修改时触发重新渲染,例如添加或删除或更新。 如果我使用todos变量提供useEffect的依赖数组,我会在控制台中得到一个无限循环日志。 如何在todos数组更新时使用useEffect触发重新渲染?

问题是 useEffect 内部没有逻辑,请参阅下面的代码

    const [todos, setTodos] = useState([]);

    useEffect(() => {
        setTodos([1])
    }, [todos])

这也会产生无限循环。 但我们总是给予相同的价值。 问题是当它被更新时,依赖是真的,所以它再次开始执行 useEffect()。 您必须提出一些具体的逻辑,例如更改length ,或者您可以采用如下所示的新状态

    const [todos, setTodos] = useState([]);
    const [load, setLoad] = useState(false);

    useEffect(() => {
        function populateTodos () {
            axios.get(`http://localhost:8000/api/all-todos`)
                .then(res => setTodos(res.data))
                .catch(err => console.log(err));
        }

        populateTodos();
    }, [load])

    console.log(todos)
    return (
        <div>
            <button
            onClick={() => {
                todos.push(1)
                setLoad(!load)
            }}
            >cilck</button>
        </div>
    );

可以通过在父组件中获取 todos提升状态,然后将结果作为 prop 传递给 useEffect 依赖于它的子组件。 任何 CRUD 操作都必须在父组件中调用才能更新列表(但您可以通过将这些函数传递给子组件来触发子组件的修改)。

否则,这也将是 Redux 的一个很好的应用程序。 您将能够使用 Redux fetch 操作初始化组件,以使用在任何组件上完成的所有 CRUD 操作填充存储,并通过修改减速器的 API 响应更新存储。 然后你可以使用 store 作为 useEffect 依赖来更新组件的本地 todo 状态。

// State
const [todos, setTodos] = useState(null);
// Redux Stores 
const todoStore = useSelector(state => state.todoStore);
// Redux Dispatch
const dispatch = useDispatch();
// Lifecycle: initialize the component's todolist
useEffect(() => {
    if (!todos) {
        // your Redux Action to call the API fetch & modify the store
        dispatch(fetchTodos); 
    }
}, [dispatch, todos]
// Lifecycle: update the todolist based on changes in the store
// (in this case I assume the data is populated into todoStore.items)
useEffect(() => {
    if (todoStore.items.length > 0) {
        setTodos(todoStore);
    }
}, [todoStore.items]

return {
    <div>{ todos.map((todo, index) => <li key={'todo_'+index}>{todo}</li>) }</div>
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM