簡體   English   中英

使用鈎子重新渲染同級組件

[英]Re-render a sibling component using hooks

我是新來的反應,我試圖讓一個組件從另一個組件重新渲染。

這是我的代碼:

const Parent = () => {
    return (
        <div>
            <Child1 />
            <Child2 />
        </div>
    )
}

我打算做的是在 Child2 有一些觸發器時更新 Child1。

我能想到的一種方法是讓父組件重新渲染,這樣 Child1 和 Child2 都會被更新。 我試圖通過提升 state 來做到這一點,但它似乎並沒有重新渲染每個子組件。 這是代碼

const Parent = () => {
    const [value, setValue] = useState('')

    const handlePost = (newValue) => {
        setValue(newValue)
    }

    return (
        <div>
            <Child1 />
            <Child2 onPost={handlePost} />
        </div>
    )
}

const Child2 = (props) => {
    // This function is executed when there is a trigger. 
    // In this case, when a post request is made to the server
    const onPost() => {
        props.handlePost('new value')
    }
}

編輯:需要重新渲染組件的原因是因為它們正在對 API 進行更改,並且這些更改需要反映在屏幕上。 它與任何 state 變量無關。

你的問題是一個XY問題。 在給出的示例中, Child1 重新渲染是沒有意義的,因為不需要它。 從評論中,您真正的問題是您更新了一個 API,這應該會改變另一個 API 的響應。 但是,如果您已經知道響應將如何變化,並且它會發生變化,這可以反映在一個 state中,該 API 調用都會發生變化:

 function useEntries() {
   const [entries, setEntries] = useState([]);

   useEffect(() => {
      setEntries(getEntries());
   }, []);

   function addEntry(entry) {
     postEntry(entry);
    setEntries(prev => [...prev, entry]);
   }

   return { entries, addEntry };
 }

 function Parent() {
   const { entries, addEntry } = useEntries();

   return <>
     <Entries entries={entries} />
     <AddEntry addEntry={addEntry} />
   </>;
  }
     

  

從帖子中的評論來看,聽起來您有Child1呈現GET請求的結果(在Child1中完成)。 Child2可以通過某種請求在服務器上添加或修改 state,並且您希望觸發重新渲染以使Child1刷新 state。

普遍的問題是,只有當道具或其使用的上下文發生變化時,孩子才應該重新渲染。 我看到兩個選項如何解決這個問題:

  1. 將請求的處理提升到父級。 將請求的結果作為 props 放入要刷新的子組件中。

  2. 通過以某種方式將其設置為“臟”,使兄弟姐妹知道必須重新加載請求。 通過上下文或通過父級路由 state。

如果組件嵌套不太深,通常最好使用選項 1 go。 它可能看起來像這樣:

const Parent = () => {
  const [posts, setPosts] = useState([]);
  const fetchNewestPosts = useCallback(async () => {
    const fetched = await fetchPosts();
    setPosts(fetched);
  }, [fetchPosts, setPosts]);
  const handleSubmit = useCallback(async (event) => {
    const newPost = getValuesFromSubmitEvent(event);
    await sendNewPost(newPost);
    // you could even set the posts here to what you think the 
    // send request will result in (see Jonas Wilms answer), like
    // setPosts(posts => [newPost, ...posts]);
    await fetchNewestPosts();
  }, [fetchNewestPosts, getValuesFromSubmitEvent, sendNewPost]);

  useEffect(() => {
    fetchNewestPosts();
  }, [fetchNewestPosts]);

  return (
    <div>
      <Child1 posts={posts} />
      <Child2 submitNewPost={submitNewPost} />
    </div>
  );
);

const Child1 = ({posts}) => {
  return (
    <ul>{posts.map(post => <li key={post.id}>post.title</li>)}</ul>
  );
);

const Child2 = ({submitNewPost}) => {
  return (
    <form onSubmit={submitNewPost}>...</form>
  );
);

作為一個很好的副作用, Child1Child2現在需要更少的邏輯,並且可以獨立於fetchPostssendNewPost函數進行樣式設置。

Ciao,可以說 Child1 必須在handlePost上重新渲染。 您的父組件將是:

const Parent= () => {
const [value, setValue] = useState('')
const [rerender, setrerender] = useState(false)

const handlePost = (newValue) => {
    setValue(newValue);
    let setrerender_temp = rerender;
    setrerender(!setrerender_temp);
}

return (
    <div>
        <Child1 rerender={rerender} />
        <Child2 onPost={handlePost} />
    </div>
)
}

然后,在您的 Child1 組件中:

import React, { useReducer, useEffect } from 'react';
...

export default function Child1(props) {
   const [,forceRender] = useReducer((s) => s+1, 0);
   useEffect(() => forceRender(), [props.rerender]);
   ...
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM