我是新来的反应者,我正在尝试从另一个组件重新渲染一个组件。
这是我的代码:
const Parent = () => {
return (
<div>
<Child1 />
<Child2 />
</div>
)
}
我打算做的是在Child2触发某些事件时更新Child1。
我能想到的一种方法是让父组件重新渲染,这样Child1和Child2都将被更新。我试图通过解除状态来做到这一点,但是它似乎并没有重新渲染每个子组件。这是代码
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进行更改,并且这些更改需要反映在屏幕上。它与任何状态变量无关。
答案 0 :(得分:0)
Ciao,可以说必须在handlePost
上重新渲染Child1。您的父组件将是:
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]);
...
}
答案 1 :(得分:0)
您的问题是XY问题。在给出的示例中,Child1重新渲染没有意义,因为不需要它。从注释中,您的实际问题是您更新了一个API,这应该会更改另一个API的响应。但是,如果您已经知道响应将如何变化以及将如何变化,则可以在两个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} />
</>;
}
答案 2 :(得分:0)
从帖子中的评论看来,您Child1
展示了GET
请求的结果(已在Child1
中完成)。 Child2
可以通过某种请求在服务器上添加或修改该状态,并且您想触发重新渲染以使Child1
刷新状态。
一般的问题是,只有在道具或其使用的上下文发生变化时,孩子才应该重新渲染。我看到了两种解决方法:
将对请求的处理提升到父级。将请求的结果作为道具放入您要刷新的子组件中。
通过以某种方式将其设置为“脏”,使同级节点意识到必须重新加载该请求。通过上下文或通过父级路由状态。
通常,如果组件的嵌套不是太深,则最好使用选项1。看起来可能像这样:
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>
);
);
作为一个很好的副作用,Child1
和Child2
现在需要少得多的逻辑,并且可以独立于fetchPosts
和sendNewPost
函数来设置样式。