如何在状态更改时重新渲染功能组件?
How to rerender functional component on state change?
我希望我的功能组件在状态“dataRes”更改时重新呈现。下面的代码是整个组件,但在第一次登录时我必须手动重新加载以显示 avatar/username 等
只要“loggedin”变为“true”,它就会重新呈现并显示用户名。好吧,显示效果非常好,只是第一次重新渲染没有...
分量:
function Username() {
const cookies = new Cookies();
const [username, setUsername] = useState(false);
const [loading, setLoading] = useState(true);
const [shortened, setShortened] = useState(false)
const authLink = "https://discord.com/api/oauth2/authorize?client_id=" + clientID + "&redirect_uri=" + clientRedirect + "&response_type=code&scope=identify%20guilds"
const [loggedin, setLoggedin] = useState(false);
const history = useHistory();
const [data, setData] = useState(null);
const [dataRes, setDataRes] = useState(false);
useEffect(() => {
fetch('SomeAPIUrlHere', {
method: "POST",
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ token: cookies.get("someCookie") })
})
.then((res) => res.json())
.then((data) => {
setData(data)
setDataRes(true)
})
}, []);
try {
if(dataRes !== false) {
if(data.username) {
if(username != data.username){
if(data.username.length > 10) {
setShortened(true)
}
setDataRes(false)
setUsername(true)
setLoggedin(true)
setLoading(false)
}
}
}
} catch(error) {
console.log(error)
}
useEffect(() => {
setTimeout(() => {
setLoading(false)
}, 1000)
}, [])
const SignOut = () => {
const cookies = new Cookies();
cookies.remove("us_au_tok")
history.push("/")
window.location.reload(false)
}
return(
<div className="flex float-left">
<a href={loggedin === false ? authLink : "/dashboard"} className={loggedin === false ? "shadow-2xl text-center text-white bg-gray rounded-2xl p-2 lg:px-5 md:px-5 sm:pl-3.5 xs:pl-3.5 mr-2 block lg:w-40 md:w-40" : "text-center text-white rounded-2xl p-2 lg:px-5 md:px-5 sm:pl-3 xs:pl-3 mr-2 block lg:w-48 md:w-48"}>
<div className={loading === true ? "md:w-8 lg:w-8 sm:w-7 xs:w-7 m-auto text-center" : "m-auto text-center"}>
<div className="flex justify-nter">
{loggedin === true ? <img src={"https://cdn.discordapp.com/avatars/" + data.userid + "/" + data.avatar + ".png?size=1024"} alt="Useravatar" className="lg:max-h-50 md:max-h-50 sm:max-h-35 xs:max-h-35 rounded-full mr-2"></img> : ""}
{loading === true ? <img src={LoadingSVG} alt='Loading Animation'/> : <p className="hover:text-brightgray duration-300 lg:m-auto md:m-auto sm:my-auto xs:my-auto">{loggedin === true ? <span>{shortened === false ? data.username : data.username.substring(0, 10) + "..."}</span> : "Login"}</p> }
</div>
</div>
</a>
{loggedin === true ? <button onClick={SignOut}><FontAwesomeIcon icon={faSignOutAlt} className="text-white mr-4" title="Sign Out" /></button> : ""}
</div>
)
};
您应该将 dataRes
作为第二个参数传递给 useEffect
The second argument to useEffect is an array of dependencies . If you
want to control when effect is to be executed after mounting the
component, then pass an array of dependencies as the second argument
这是一个示例:
const {useEffect,useState} = React;
function App () {
const [data, setData] = useState(null);
const [dataRes, setDataRes] = useState(false);
useEffect(() => {
if (dataRes) {
fetch("https://gorest.co.in/public/v1/users", {
method: "GET"
})
.then((res) => res.json())
.then((data) => {
setData(data);
//setDataRes(true);
});
} else {
setData([]);
}
}, [dataRes]);
const handleClick = () => {
setDataRes((prev) => !prev);
};
return (
<div className="App">
<button onClick={handleClick}>change dataRes</button>
<div>{`dataRes: ${dataRes}`}</div>
<hr />
<div>{JSON.stringify(data)}</div>
</div>
);
}
ReactDOM.render( <App/> ,
document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>
我希望我的功能组件在状态“dataRes”更改时重新呈现。下面的代码是整个组件,但在第一次登录时我必须手动重新加载以显示 avatar/username 等
只要“loggedin”变为“true”,它就会重新呈现并显示用户名。好吧,显示效果非常好,只是第一次重新渲染没有...
分量:
function Username() {
const cookies = new Cookies();
const [username, setUsername] = useState(false);
const [loading, setLoading] = useState(true);
const [shortened, setShortened] = useState(false)
const authLink = "https://discord.com/api/oauth2/authorize?client_id=" + clientID + "&redirect_uri=" + clientRedirect + "&response_type=code&scope=identify%20guilds"
const [loggedin, setLoggedin] = useState(false);
const history = useHistory();
const [data, setData] = useState(null);
const [dataRes, setDataRes] = useState(false);
useEffect(() => {
fetch('SomeAPIUrlHere', {
method: "POST",
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ token: cookies.get("someCookie") })
})
.then((res) => res.json())
.then((data) => {
setData(data)
setDataRes(true)
})
}, []);
try {
if(dataRes !== false) {
if(data.username) {
if(username != data.username){
if(data.username.length > 10) {
setShortened(true)
}
setDataRes(false)
setUsername(true)
setLoggedin(true)
setLoading(false)
}
}
}
} catch(error) {
console.log(error)
}
useEffect(() => {
setTimeout(() => {
setLoading(false)
}, 1000)
}, [])
const SignOut = () => {
const cookies = new Cookies();
cookies.remove("us_au_tok")
history.push("/")
window.location.reload(false)
}
return(
<div className="flex float-left">
<a href={loggedin === false ? authLink : "/dashboard"} className={loggedin === false ? "shadow-2xl text-center text-white bg-gray rounded-2xl p-2 lg:px-5 md:px-5 sm:pl-3.5 xs:pl-3.5 mr-2 block lg:w-40 md:w-40" : "text-center text-white rounded-2xl p-2 lg:px-5 md:px-5 sm:pl-3 xs:pl-3 mr-2 block lg:w-48 md:w-48"}>
<div className={loading === true ? "md:w-8 lg:w-8 sm:w-7 xs:w-7 m-auto text-center" : "m-auto text-center"}>
<div className="flex justify-nter">
{loggedin === true ? <img src={"https://cdn.discordapp.com/avatars/" + data.userid + "/" + data.avatar + ".png?size=1024"} alt="Useravatar" className="lg:max-h-50 md:max-h-50 sm:max-h-35 xs:max-h-35 rounded-full mr-2"></img> : ""}
{loading === true ? <img src={LoadingSVG} alt='Loading Animation'/> : <p className="hover:text-brightgray duration-300 lg:m-auto md:m-auto sm:my-auto xs:my-auto">{loggedin === true ? <span>{shortened === false ? data.username : data.username.substring(0, 10) + "..."}</span> : "Login"}</p> }
</div>
</div>
</a>
{loggedin === true ? <button onClick={SignOut}><FontAwesomeIcon icon={faSignOutAlt} className="text-white mr-4" title="Sign Out" /></button> : ""}
</div>
)
};
您应该将 dataRes
作为第二个参数传递给 useEffect
The second argument to useEffect is an array of dependencies . If you want to control when effect is to be executed after mounting the component, then pass an array of dependencies as the second argument
这是一个示例:
const {useEffect,useState} = React;
function App () {
const [data, setData] = useState(null);
const [dataRes, setDataRes] = useState(false);
useEffect(() => {
if (dataRes) {
fetch("https://gorest.co.in/public/v1/users", {
method: "GET"
})
.then((res) => res.json())
.then((data) => {
setData(data);
//setDataRes(true);
});
} else {
setData([]);
}
}, [dataRes]);
const handleClick = () => {
setDataRes((prev) => !prev);
};
return (
<div className="App">
<button onClick={handleClick}>change dataRes</button>
<div>{`dataRes: ${dataRes}`}</div>
<hr />
<div>{JSON.stringify(data)}</div>
</div>
);
}
ReactDOM.render( <App/> ,
document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>