为啥在组件加载时不调用 useEffect(()=...,[]) ?

Posted

技术标签:

【中文标题】为啥在组件加载时不调用 useEffect(()=...,[]) ?【英文标题】:Why is useEffect(()=...,[]) not being called on component load?为什么在组件加载时不调用 useEffect(()=...,[]) ? 【发布时间】:2022-01-07 05:29:42 【问题描述】:

有许多与 useEffect() 和在初始页面渲染时运行有关的问题。即使在确保我的代码在传递给 useEffect 的参数方面是正确的之后,我也遇到了同样的问题。

useEffect(() => 
        const token = Cookies.get('token');
        setRole(Cookies.get('role'));
        fetch(`$process.env.API_URL/user/user-details`, 
            method: "POST",
            headers: 
                "Content-Type": "application/json",
            ,
            body: JSON.stringify(
                "user_id": role,
                "language": "en",
                "api_token": token
            )
        )
            .then((user) => user.json())
            .then((thisUserData) => 
                if (thisUserData.status_code == 200) 
                    setThisUser(thisUserData)
                
            )
    , [])

由于某种原因,组件安装后似乎没有调用它。

这是完整的页面代码:

import Header from "../../../components/header"
import  useRouter  from "next/router"
import Link from 'next/link'
import Pagination from "../../../components/datatable/pagination"
import Cookies from "js-cookie"
import  parseCookies  from "nookies"
import  useState, useEffect  from "react"
import  Modal, Button  from "react-bootstrap";
import UserSidebar from "../../../components/user_sidebar"
import TabButtonUser from "../../../components/tabbuttonuser"
import Address from "../../../components/address"


const AdminUsers = ( data ) => 

    const router = useRouter()
    // const limit = 3
    // const lastPage = Math.ceil(totalPage / limit)
    // console.log(data)
    // console.log(listUsers)

    /**
     * Manage states
     */

    const [show, setShow] = useState(false);
    const [isEdit, setIsEdit] = useState(false);

    const [fullNname, setFullName] = useState("");
    const [emailID, setEmailID] = useState("");
    const [country_code, setCountry_code] = useState("");
    const [phone_number, setPhone_number] = useState("");
    const [company_access, setCompany_access] = useState("");
    const [isActive, setActive] = useState("");
    const [userID, setUserId] = useState("");
    const [role, setRole] = useState("");
    const [thisUserData, setThisUser] = useState()

    useEffect(() => 
        const token = Cookies.get('token');
        setRole(Cookies.get('role'));
        fetch(`$process.env.API_URL/user/user-details`, 
            method: "POST",
            headers: 
                "Content-Type": "application/json",
            ,
            body: JSON.stringify(
                "user_id": role,
                "language": "en",
                "api_token": token
            )
        )
            .then((user) => user.json())
            .then((thisUserData) => 
                if (thisUserData.status_code == 200) 
                    setThisUser(thisUserData)
                
            )
    , [])
    
    /**
     * Clear values
     */
    const handleClose = () => 
        setShow(false)
        setIsEdit(false);
        setUserId("")
        setFullName("");
        setEmailID("");
        setCountry_code("");
        setPhone_number("");
    ;
    const handleShow = () => setShow(true);





    /**
     * Add User
     * @param * e 
     * @returns 
     */
    const addUser = async (e) => 

        e.preventDefault();
        const token = Cookies.get('token');
        if (!token) 
            return 
                redirect: 
                    destination: '/',
                    permanent: false,
                ,
            
        
        const resUser = await fetch(`$process.env.API_URL/user/create-sub-admin`, 
            method: "POST",
            headers: 
                "Content-Type": "application/json",
            ,
            body: JSON.stringify(
                "full_name": fullNname,
                "email_id": emailID,
                "country_code": "+1",
                "phone_number": phone_number,
                "api_token": token
            )
        )

        const res2User = await resUser.json();
        console.log(res2User);
        if (res2User.status_code == 200) 
            handleClose();
            setFullName("");
            setEmailID("");
            setCountry_code("");
            setPhone_number("");
        
    

    /**
     * Get user details basis of user id for edit purpose
     * @param * id 
     * @returns 
     */
    const getUser = async (id) => 
        // e.preventDefault();
        setIsEdit(true);
        setShow(true);
        setUserId(id)
        const token = Cookies.get('token');
        if (!token) 
            return 
                redirect: 
                    destination: '/',
                    permanent: false,
                ,
            
        
        const userData = await fetch(`$process.env.API_URL/user/user-details`, 
            method: "POST",
            headers: 
                "Content-Type": "application/json",
            ,
            body: JSON.stringify(
                "user_id": id,
                "language": "en",
                "api_token": token
            )

        )
        const userData2 = await userData.json();
        console.log(userData2);
        if (userData2.status_code == 200) 
            // handleClose();
            setFullName(userData2?.data?.full_name);
            setEmailID(userData2?.data?.email_id);
            setCountry_code(userData2?.data?.phone_number?.country_code);
            setPhone_number(userData2?.data?.phone_number?.phone_number);
        
    

    /**
     * Remove user 
     * Api is pending
     * @param * id 
     */
    const removeUser = async (id) => 

    
    /**
     *Update User
     *
     * @return * 
     */
    const updateUser = async () => 
        // e.preventDefault();
        const token = Cookies.get('token');
        if (!token) 
            return 
                redirect: 
                    destination: '/',
                    permanent: false,
                ,
            
        
        const resUser = await fetch(`$process.env.API_URL/user/update-user`, 
            method: "POST",
            headers: 
                "Content-Type": "application/json",
            ,
            body: JSON.stringify(
                "user_id": userID,
                "full_name": fullNname,
                "email_id": emailID,
                "country_code": "+1",
                "phone_number": phone_number,
                "api_token": token,
                "is_active": isActive
            )

        )
        const res2User = await resUser.json();
        console.log(res2User);
        if (res2User.status_code == 200) 

            setFullName("");
            setEmailID("");
            setCountry_code("");
            setPhone_number("");
            setIsEdit(false);
            setShow(false);
            setUserId("")
        
    

    const address = 
        "address_line": "",
        "city_name": "",
        "state_name": "",
        "zip_code": ""
    
    return (
        <>
            <Header />
            <div className="container">
                <div className="row">
                    <div className="col-3">
                        <UserSidebar data=thisUserData />
                    </div>
                    <div className="col">
                        <div className="sidebarwrap">
                            /* <TabButtonUser id=data?._id /> */
                            <h3 className="acc_title">My Company</h3>
                            <h2 className="login_name">Alliance Credit</h2>
                            <div className="acc_email">
                                <a href="mailto:email@company.com">email@company.com</a>
                            </div>
                            <div className="acc_phone">+1234567890</div>
                            <Address address=address />


                            <div className="ac_left acc_title">All Team Members</div>
                            <div className="ac_right">
                                role.indexOf('admin') > -1 ?
                                    <button className="btn btnedit" onClick=handleShow>Add Sub-Admin</button>
                                    : ''
                            </div>
                            <div className="clearfix"></div>
                            <div className="listing">
                                <table id="example" className="table table-striped">

                                    <thead>
                                        <tr>
                                            <th><div>Sr. Number</div></th>
                                            <th><div>User Name</div></th>
                                            <th><div>Date Added</div></th>
                                            <th><div>Email</div></th>

                                            <th><div>Actions</div></th>
                                        </tr>
                                    </thead>
                                    <tbody>
                                        data?.map((item, index) => (


                                            <tr key=index>
                                                <td>index + 1</td>
                                                <td>item.full_name</td>
                                                <td>item.date_added</td>
                                                <td>item.email_id</td>
                                                <td>
                                                    <>
                                                        <button className="btn viewmore" onClick=() => getUser(item._id)>Edit User</button>
                                                    </>
                                                </td>
                                            </tr>
                                        ))
                                    </tbody>
                                </table>
                                /* <Pagination page=page totalPage=totalPage lastPage=lastPage /> */
                            </div>
                        </div>
                    </div>
                </div>
            </div>


            <Modal show=show onHide=handleClose>
                <Modal.Header closeButton>
                    <Modal.Title>isEdit == false
                        ? "Add Sub-Admin"
                        : "Edit Sub-Admin"
                    </Modal.Title>
                </Modal.Header>
                <Modal.Body>
                    <div className="popupform">
                        <form method="POST">
                            <div className="row">
                                <div className="col">


                                    <label htmlFor="fullname" className="form-label">Full Name</label>
                                    <input className="form-control" name="fullname" type="text" id="fullname" value=fullNname onChange=(e) => setFullName(e.target.value) />
                                </div>
                            </div>
                            <div className="row">
                                <div className="col">
                                    <label htmlFor="emailID" className="form-label">Email</label>
                                    <input className="form-control" name="emailID" type="text" id="emailID" value=emailID onChange=(e) => setEmailID(e.target.value) />
                                </div>
                            </div>
                            <div className="row">
                                <div className="col">
                                    <label htmlFor="phone_number" className="form-label">Phone Number</label>
                                    <input className="form-control" name="phone_number" type="text" id="phone_number" value=phone_number onChange=(e) => setPhone_number(e.target.value) />
                                </div>
                            </div>
                            <div className="row">
                                <div className="col">
                                    isEdit ? (
                                        <>
                                            <label htmlFor="phone_number" className="form-label">Active status</label>
                                            <select className="form-control form-select" onChange=(e) => setActive(e.target.value)>
                                                <option value="0">Active</option>
                                                <option value="1">Deactivate</option>
                                            </select>
                                        </>
                                    ) : ''
                                    
                                </div>
                            </div>
                            <div>
                                <input className="form-control" name="userID" type="hidden" id="company_logo_en" value=userID />
                            </div>
                        </form>
                    </div>
                </Modal.Body>
                <Modal.Footer>
                    isEdit == false
                        ? <>
                            <Button variant="secondary" className="btn btnedit" onClick=handleClose>Cancel</Button>
                            <Button variant="primary" onClick=addUser>Add User</Button>
                        </>
                        :
                        <>
                            <Button variant="primary" className="btn btnremove" onClick=removeUser>Remove User</Button>
                            <Button variant="primary" className="btn btnedit">Reset User</Button>
                            <Button variant="primary" onClick=updateUser>Save</Button>
                        </>
                    
                </Modal.Footer>
            </Modal>
        </>
    )


/**
 *
 *
 * @export
 * @param *  query:  page = 1, data = null, totalPage = 10  
 * @return * 
 */
// export async function getServerSideProps( query:  page = 1, data = null, totalPage = 10  ) 
export async function getServerSideProps(ctx) 
    // const start = +page === 1 ? 0 : (+page + 1)

    // const  locale, locales, defaultLocale, asPath  = useRouter();
    const  token  = parseCookies(ctx)

    if (!token) 
        return 
            redirect: 
                destination: '/',
                permanent: false,
            ,
        
    

    const res = await fetch(`$process.env.API_URL/user/list-sub-admin`, 
        method: "POST",
        headers: 
            "Content-Type": "application/json",
        ,
        body: JSON.stringify(
            "language": 'en',
            "api_token": token,
        )

    )

    const data = await res.json()


    /** 
     * limit, start, search item
     */
    return 
        props: 
            data: data?.data || [],
        
    



export default AdminUsers

我确信这是我错过的一些简单的事情(通常是这样),但我似乎无法发现它。

谢谢。

【问题讨论】:

“这是完整的页面代码” 这并不是真的那么有用。我们只看到AdminUsers 组件。这还不足以用于运行您的代码。如果你为你的项目创建了一个在线沙箱会更好。例如,试试codesandbox.io。 它真的没有被调用,还是由于role 仍然具有其初始值,您是否从获取请求中得到了非 200 响应?设置状态是一个异步操作:***.com/questions/38558200/…. 它似乎没有被调用,因为我的断点都没有命中函数中的任何地方。但是@Max给出的答案解决了这个问题。似乎对 state 的调用导致页面在 useEffect() 完成之前重新呈现,使其看起来好像根本没有被调用。去掉 useState() 调用就完美解决了。 【参考方案1】:

我不清楚这个问题,但我试着写下我所看到的:你已经定义了 useEddect 和没有 deps 的 fetch。在该提取中,您使用角色状态,该状态在第一次初始化为空字符串。您在同一个 useEffect 中使用 setRole 设置角色,但由于前面的原因,这没有效果。

我的建议是删除角色状态并重新定义 useEffect 如下:

useEffect(() => 
    const token = Cookies.get('token');
    const role = Cookies.get('role');
    fetch(`$process.env.API_URL/user/user-details`, 
      method: 'POST',
      headers: 
        'Content-Type': 'application/json',
      ,
      body: JSON.stringify(
        user_id: role,
        language: 'en',
        api_token: token,
      ),
    )
      .then((user) => user.json())
      .then((thisUserData) => 
        if (thisUserData.status_code == 200) 
          setThisUser(thisUserData);
        
      );
  , []);

【讨论】:

以上是关于为啥在组件加载时不调用 useEffect(()=...,[]) ?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 useState 钩子在 useEffect() 中使用循环时不更新

为啥每次渲染都会调用 `useEffect` 的清理功能?

渲染组件时不触发 useEffect

useEffect 中的套接字连接事件在创建组件时不起作用,但在 React 中刷新页面后起作用

React Hooks:即使使用空数组作为参数,也会调用两次 useEffect()

为啥我的组件在使用 React 的 Context API 和 useEffect 挂钩时会渲染两次?