获取数据后不断输入 useEffect



我在Profile组件中有我的useEffect,如下所示:

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;
}
}

所以我想通了。问题是每次组件更改时都会调用 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]);

您的答案可能会起作用,因为数据只会被获取一次,并且userPost永远不会更改引用。

通常,将 REST 数据置于状态中比您执行的操作要复杂一些。如果您需要数据,则容器将选择如下所示的数据:

const NOT_REQUESTED = {requested:false}
state => state.data.someData || NOT_REQUESTED

然后,如果未请求数据,组件可以请求数据。

useEffect(()=>requested || fetchData(),[requested])

化简器将设置请求和加载作为对请求操作的响应:

{
...state,
data: {
...state.data,
someData: { requested: true, loading: true },
},
};

现在,当您的组件将重新渲染但未调用fetchData时,因为请求为 true。

当请求成功时,化简器可以在数据成功操作上写入结果:

{
...state,
data: {
...state.data,
someData: {
...state.data.someData,
loading: false,
data: action.data,
},
},
};

这不是服务器端过滤,排序,过时数据或错误处理,但我希望您能理解。

如果您希望组件调度操作来加载数据,那么您的容器/选择器需要生成指示是否已请求数据的 props。

相关内容

  • 没有找到相关文章

最新更新