简体   繁体   English

如何使 UseEffect 挂钩逐步运行而不是持续运行?

[英]How do I make UseEffect hook run step by step and not last?

I have UseEffect hook that fetches data from DB and I want it to run FIRST in my component, but it runs last.我有从数据库中获取数据的 UseEffect 钩子,我希望它在我的组件中首先运行,但它最后运行。

How do I make it run before "console.log(titleee)"?如何让它在“console.log(titleee)”之前运行?

Code:代码:

 const [cPost, setCPost] = useState([]);
  const postId = id.match.params.id;

  useEffect(() => {
    axios.get('http://localhost:5000/posts/'+postId)
      .then(posts => {
        setCPost(posts.data);
        console.log("test");
      })
  }, []);



const titleee = cPost.title;
console.log(titleee);


I don't think that's the correct path that you want to take.我认为这不是您想要采取的正确道路。

In order to show the cPost on your page after the request /posts/+postId finished you can opt-out for two following options.为了在请求/posts/+postId完成后在您的页面上显示cPost ,您可以选择退出以下两个选项。

You can show a "loader" to the user if the cPost data is crucial for your whole component.如果cPost数据对您的整个组件至关重要,您可以向用户显示“加载器”。

const [fetchingCPost, setFetchingCPost] = useState(false)
const [cPost, setCPost] = useState({});
const postId = id.match.params.id;

useEffect(() => {
  setFetchingCPost(true)
  axios.get('http://localhost:5000/posts/'+postId)
    .then(posts => {
      setFetchingCPost(false)
      setCPost(posts.data);
  })
}, []);

return fetchingCPost && <div>Loading</div>

Or you can have some default values set from the start for cPost .或者,您可以从一开始就为cPost设置一些默认值。 Just to make sure that your code doesn't break.只是为了确保您的代码不会中断。 I think the first solution might be more UX acceptable.我认为第一个解决方案可能更容易被 UX 接受。

const [cPost, setCPost] = useState({title: '', description: ''});

If you want to store title as a separate variable you can use useMemo for instance or do it via useState same as with cPost .如果您想将title存储为单独的变量,您可以使用useMemo或通过与useState相同的cPost进行操作。 But even then you can't "create" it after the request finishes, you can simply change its value .但即便如此,您也无法在请求完成后“创建”它,您可以简单地更改它的 value

In case you want to use useMemo you can make it dependent on your cPost .如果你想使用useMemo ,你可以让它依赖于你的cPost

const cPostTitle = useMemo(() => {
  return !!cPost.title ? cPost.title : ''
}, [cPost])

You have to change you'r way of thinking when programming in react.在进行 React 编程时,您必须改变您的思维方式。 It is important to know how react works.了解 React 的工作原理很重要。 React does not support imperative programming, it rather support declarative and top down approach, in which case you have to declare your markup and feed it with you'r data then the only way markup changes is by means of changing you'r data. React 不支持命令式编程,而是支持声明式和自上而下的方法,在这种情况下,您必须声明您的标记并将其与您的数据一起提供,然后标记更改的唯一方法是通过更改您的数据。 So in you'r case you are declaring a watched variable using useState hook const [cPost, setCPost] = useState([]);因此,在您的情况下,您正在使用 useState hook const [cPost, setCPost] = useState([]);声明一个监视变量, this variable (cPost) has initial values of [] then react continues rendering you'r markup using initial value, to update the rendered title to something you get from a network request (eg: a rest API call) you use another hook which is called after you'r component is rendered (useEffect). ,此变量(cPost)的初始值为[]然后反应继续使用初始值渲染您的标记,以将渲染的标题更新为您从网络请求获得的内容(例如:rest API 调用)您使用另一个挂钩在渲染组件后调用(useEffect)。 Here you have chance to fetch data and update you'r state.在这里,您有机会获取数据并更新您的 state。 To do so you did as following:为此,您执行以下操作:

  useEffect(() => {
    axios.get('http://localhost:5000/posts/'+postId)
      .then(posts => {
        setCPost(posts.data);
      })
  }, []);

this code results in a second render because part of data is changes.此代码导致第二次渲染,因为部分数据是更改。 Here react engine goes ahead and repaint you'r markup according data change.这里反应引擎继续并根据数据更改重新绘制您的标记。

If you check this sandbox you'll see two console logs, in first render title is undefined in second render it's something we got from network.如果您检查此沙箱,您将看到两个控制台日志,在第一个渲染中,标题在第二个渲染中未定义,这是我们从网络获得的。

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

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