我的useEffect
在Profile
组件中是这样的:
const [mappedPosts, setMappedPosts] = useState(null);
useEffect(() => {
fetchMedia();
if (userPosts) {
console.log("This keeps entering!");
const mapped = userPosts.map((post, index) => (
<View key={index}>
<Text>{post.title}</Text>
</View>
));
setMappedPosts(mapped);
}
}, []);
我的Profile
组件返回,
return mappedPosts ? (
<View>
{mappedPosts}
</View>
) : (
<Spinner />
);
我的问题如下:
Spinner
组件在出现以下情况时呈现:
useEffect(() => {
fetchMedia();
if (userPosts) {...};
setMappedPosts(mapped);
}
}, []);
或
useEffect(() => {
fetchMedia();
if (userPosts) {...};
setMappedPosts(mapped);
}
}, [mappedPosts]);
当我拥有以下内容时,将呈现适当的数据
useEffect(() => {
fetchMedia();
if (userPosts) {...};
setMappedPosts(mapped);
}
}, [userPosts]);
或
useEffect(() => {
fetchMedia();
if (userPosts) {...};
setMappedPosts(mapped);
}
});
最后两个问题是console.log("This keeps entering!");
行被一遍又一遍地打印,表明该组件一直在重新呈现。我不确定我在做什么错。下面的变体也保持了组件的重新渲染:
const [mappedPosts, setMappedPosts] = useState(null);
useEffect(() => {
fetchMedia();
if (userPosts && mappedPosts === null) {
console.log("entered!");
const mapped = userPosts.map((post, index) => (
<View key={index}>
<Text>{post.title}</Text>
</View>
));
setMappedPosts(mapped);
}
}, [userPosts]);
console.log("am I being re-rendered?");
return mappedPosts ? (
<View>
{mappedPosts}
</View>
) : (
<Spinner />
);
我之所以知道这一点,是因为console.log("am I being re-rendered?");
可以使打印不间断...即使数据已经被渲染并正确显示在屏幕上(我使用的是react-native)。
Profile
组件从redux存储中获取userPosts
:
const Profile = ({
navigation,
posts: { userPosts, loading },
auth: { isAuthenticated },
fetchMedia,
checkAuth
}) => {
const [mappedPosts, setMappedPosts] = useState(null);
useEffect(() => {
fetchMedia();
.......
fetchMedia
:
export const fetchMedia = () => async dispatch => {
dispatch({
type: FETCH_MEDIA
});
try {
const response = await axios.get(`http://${GATEWAY}:5000/api/posts/user`);
dispatch({
type: MEDIA_SUCCESS,
payload: response.data
});
} catch (err) {
dispatch({
type: MEDIA_FAIL
});
}
};
减速器:
const initialState = {
userPosts: null,
loading: false
};
export default function(state = initialState, action) {
const { type, payload } = action;
switch (type) {
case FETCH_MEDIA:
return {
...state,
loading: true
};
case MEDIA_SUCCESS:
return {
...state,
userPosts: payload,
loading: false
};
case MEDIA_FAIL:
return {
...state,
loading: false
};
default:
return state;
}
}
答案 0 :(得分:2)
您的答案可能会起作用,因为数据只会被提取一次,而userPost
永远不会更改引用。
通常,将REST数据置于状态比您做的要复杂一些。如果您需要数据,则容器将选择数据,如下所示:
const NOT_REQUESTED = {requested:false}
state => state.data.someData || NOT_REQUESTED
然后,该组件可以请求数据。
useEffect(()=>requested || fetchData(),[requested])
Reducer将设置请求并加载为对请求操作的响应:
{
...state,
data: {
...state.data,
someData: { requested: true, loading: true },
},
};
现在,当您的组件将重新呈现但由于请求为true时,未调用fetchData
时。
请求成功后,reducer可以将结果写到数据成功操作上:
{
...state,
data: {
...state.data,
someData: {
...state.data.someData,
loading: false,
data: action.data,
},
},
};
这与服务器端过滤,排序,陈旧数据或错误处理无关,但我希望您能理解。
如果您希望组件分派操作以加载数据,则您的容器/选择器需要产生道具来指示是否已请求数据。
答案 1 :(得分:2)
所以我知道了。问题是组件每次更改时都会调用fetchMedia。因此,一旦userPosts
被提取..它们又被提取了。然后再次。然后再次。这就是组件不断重新渲染的原因。这是我所做的更改:
useEffect(() => {
if (userPosts) {
console.log("entered!");
const mapped = userPosts.map((post, index) => (
<View key={index}>
<Text>{post.title}</Text>
</View>
));
setMappedPosts(mapped);
} else {
fetchMedia();
}
}, [userPosts]);