我对将功能组件与React结合使用感到困惑。
这是我的组件,实现细节并不那么重要:
const Trending = ({ match, actions, trendingPlaces, meConfig }) => {
const [GeoView, setGeoView] = useState(AcceptCurrentLocationPlaceholder);
const menuItem = match.params[0];
console.log('*** Trending ***');
if (runsOnClient()) {
useEffect(() => {
console.log('effect is run');
if (!requiresGeolocation(menuItem)) return;
if (meConfig.isCustomLocationSet) {
setGeoView(
getComponentForMenuItem(menuItem));
return;
}
if (geolocationServiceIsAvailable()) {
const getCurrentLocation = async () => {
try {
setGeoView(AcceptCurrentLocationPlaceholder);
const currentPosition = await getCurrentPosition(
getConfig().googleMaps.currentPositionOptions);
setGeoView(getComponentForMenuItem(menuItem));
} catch (err) {
setGeoView(DeniedCurrentLocationPlaceholder);
}
};
getCurrentLocation();
} else {
// Display the view mentioning 'geolocation is not available' and set custom location
}
}, [menuItem]);
}
// Fetch trending places
const { fetchTrendingPlaces } = actions;
useEffect(() => {
fetchTrendingPlaces();
}, []);
return (
<section id="zp-trending">
<TrendingMenu match={ match } />
<div id="zp-trending-body">
<Route path={'/trending/list'} component={ GeoView } />
<Route path={'/trending/map'} component={ GeoView } />
<Route path={'/trending/settings'} component={ TrendingSettings } />
</div>
</section>
);
};
const mapStateToProps = state => {
return {
meConfig: state.meConfig,
trendingPlaces: state.trendingPlaces
};
};
const mapDispatchToProps = (dispatch) => {
return {
actions: bindActionCreators(fetchTrendingPlaces, dispatch)
}
};
export default connect(mapStateToProps, mapDispatchToProps)(Trending);
当我检查日志时,似乎*** Trending ***
的调用不一致。似乎在每次Redux更新之后也会调用它。
那是为什么?
答案 0 :(得分:2)
问题是bindActionCreators
总是返回新的对象或函数。因此,您在每个redux更新中都会得到新的actions
。
如果要保留嵌套结构,可以执行以下操作
const mapDispatchToProps = (dispatch) => {
const actions = bindActionCreators(fetchTrendingPlaces, dispatch);
return () => ({actions})
};
或者您可以展平属性,以便通过浅层相等性检查。
const mapDispatchToProps = {
fetchTrendingPlaces
}; // pass object to connect
// use in component
const Trending = ({fetchTrendingPlaces /* the rest of your props*/}) => {
答案 1 :(得分:1)
请勿在循环,条件或嵌套函数中调用Hook。相反,请始终在您的React函数的顶层使用挂钩。通过遵循此规则,可以确保每次渲染组件时都以相同的顺序调用Hook。这就是让React在多个useState和useEffect调用之间正确保留Hook的状态的原因。 (如果您感到好奇,我们将在下面对此进行深入说明。)
不要通过常规JavaScript函数调用Hook。相反,您可以:
✅从React函数组件中调用Hook。
✅从自定义挂钩中调用挂钩(我们将在下一页中了解它们)。 通过遵循此规则,可以确保组件的所有状态逻辑从其源代码中都清晰可见。
这是违反规则的代码部分
if (runsOnClient()) {
useEffect(() => {
console.log('effect is run');
if (!requiresGeolocation(menuItem)) return;
if (meConfig.isCustomLocationSet) {
setGeoView(
getComponentForMenuItem(menuItem));
return;
}
修复可能会有帮助。
答案 2 :(得分:0)
问题是我在这里使用useState
会触发重新渲染。
其他重新渲染的触发原因:
实际上在useEffect中,看来我必须使用useState来获得条件渲染。所以我想这是预期的行为。
UI的行为符合预期,因此我认为必须重新渲染。