Jo *_*mma 5 reactjs react-native react-props react-hooks
我是React的新手,所以我希望我能正确解决这个问题。首先,我有一个名为SearchLocationsScreen的屏幕。在该屏幕内,我有一个名为Map的组件,在Map内有一个名为LocationMarker的自定义标记组件。在与Map组件相同的层次结构级别上,我有一个自定义的ModalBox,称为CheckinModal。这是一个粗略的图表可以帮助您:
在SearchLocationsScreen中,我从API调用中获取位置信息。然后,将这些位置传递到我的地图组件。在我的Map组件内部,我将标记的信息向下传递到自定义LocationMarker类,并填充地图。
目的是按下一个标记,并从底部弹出CheckinModal,并使用所按下的特定标记的信息填充它。为此,我使用useRef钩子和forwardRef钩子将对模式的引用传递给LocationMarker类。我在这里打电话ref.current.open(),模态按预期方式打开。
问题是我无法找到一种方法来从标记传递位置信息,将层次结构备份到屏幕上,再向下到模态以用相关信息填充模态。有谁知道如何实现这一目标?我将下面的代码发布到屏幕,地图组件和标记组件(不包括样式)。在此先感谢您的帮助。
SearchLocationsScreen.js
const SearchLocationsScreen = ({isFocused, navigation}) => {
const {updateLocation} = useContext(CurrentLocationContext);
// hooks
const callback = useCallback((location) => {
updateLocation(location)
}, []);
const [err] = useCurrentLocation(isFocused, callback);
const [businessLocations] = useGetLocations();
const modalRef = useRef(null);
let locations = [];
if (businessLocations) {
for (let x = 0; x < businessLocations.length; x++) {
locations.push({
...businessLocations[x],
latitude: businessLocations[x].lat,
longitude: businessLocations[x].lng,
key: x,
})
}
}
return (
<View style={{flex: 1}}>
<Map markers={locations} ref={modalRef}/>
<SearchBar style={styles.searchBarStyle}/>
{err ? <View style={styles.errorContainer}><Text
style={styles.errorMessage}>{err.message}</Text></View> : null}
<CheckinModal
ref={modalRef}
/>
</View>
);
};
Run Code Online (Sandbox Code Playgroud)
Map.js
const Map = ({markers}, ref) => {
const {state: {currentLocation}} = useContext(Context);
// todo figure out these error situations
if (!currentLocation) {
return (
<View style={{flex: 1}}>
<MapView
style={styles.map}
provider={PROVIDER_GOOGLE}
initialRegion={{
latitude: 27.848680,
longitude: -82.646560,
latitudeDelta: regions.latDelta,
longitudeDelta: regions.longDelta
}}
/>
<ActivityIndicator size='large' style={styles.indicator} />
</View>
)
}
return (
<MapView
style={styles.map}
provider={PROVIDER_GOOGLE}
initialRegion={{
...currentLocation.coords,
latitudeDelta: regions.latDelta,
longitudeDelta: regions.longDelta
}}
showsUserLocation
>
{ markers ? markers.map((marker, index) => {
return <LocationMarker
ref={ref} // passing the ref down to the markers
key={index}
coordinate={marker}
title={marker.company}
waitTime={ marker.wait ? `${marker.wait} minutes` : 'Open'}
/>;
}) : null}
</MapView>
)
};
const forwardMap = React.forwardRef(Map);
export default forwardMap;
Run Code Online (Sandbox Code Playgroud)
LocationMarker.js
const LocationMarker = ({company, coordinate, title, waitTime, onShowModal}, ref) => {
return (
<View>
<Marker
coordinate={coordinate}
title={title}
onPress={() => {
console.log(ref);
ref.current.open();
}}
>
<Image
source={require('../../assets/marker2.png')}
style={styles.locationMarker}/>
<View style={styles.waitContainer}><Text style={styles.waitText}>{waitTime}</Text></View>
</Marker>
</View>
)
};
const forwardMarker = React.forwardRef(LocationMarker);
export default forwardMarker;
Run Code Online (Sandbox Code Playgroud)
我在阿尔瓦罗对我的主要帖子的评论的帮助下弄清楚了这一点。
这就是我所做的。首先,我将生成LocationMarker的代码移至SearchLocationsScreen。无论如何,我已经在该屏幕上访问这些标记所需的位置(最初我将这些位置传递给地图组件并在那里创建它们)。在SearchLocationsScreen中,我循环遍历所有位置以生成 LocationMarker ,添加一个使用useReducer挂钩来存储模态状态的回调。由于它们都位于同一级别,因此我可以使用减速器状态中的正确数据填充模态的字段。该回调被传递到LocationMarker。然后在LocationMarker onPress 中我调用这个方法。一切都按预期进行。这是更新后的代码:
搜索地点屏幕
const SearchLocationsScreen = ({isFocused, navigation}) => {
const {updateLocation} = useContext(CurrentLocationContext);
// hooks
const callback = useCallback((location) => {
updateLocation(location)
}, []);
const [err] = useCurrentLocation(isFocused, callback);
const [businessLocations] = useGetLocations();
const modalRef = useRef(null);
let locations = [];
if (businessLocations) {
for (let x = 0; x < businessLocations.length; x++) {
locations.push({
...businessLocations[x],
latitude: businessLocations[x].lat,
longitude: businessLocations[x].lng,
key: x,
})
}
}
const modalReducer = (state, action) => {
console.log("payload: ", action.payload);
switch (action.type) {
case 'show_modal':
return {...state,
companyName: action.payload.companyName,
companyAddress: action.payload.companyAddress,
waitTime: action.payload.waitTime
};
default:
return state;
}
};
const [modalState, dispatch] = useReducer(modalReducer, {
companyName: "Company Name",
companyAddress: "123 Elm St",
waitTime: 0
});
const createMarkers = () => {
let result = [];
if (locations) {
for (let i = 0; i < locations.length; i++) {
result.push(
<LocationMarker
key={i}
id={i}
coordinate={locations[i]}
title={locations[i].company}
waitTime={locations[i].wait ? `${locations[i].wait} minutes` : 'Closed'}
onShowModal={() => {
dispatch({
type: 'show_modal', payload: {
companyName: locations[i].company,
companyAddress: locations[i].address,
waitTime: locations[i].wait,
}
});
modalRef.current.open();
}}
/>
)
}
}
return result;
};
return (
<View style={{flex: 1}}>
<Map markers={createMarkers()}/>
{/*<Map ref={modalRef} markers={...createMarkers()} />*/}
<SearchBar style={styles.searchBarStyle}/>
{err ? <View style={styles.errorContainer}><Text
style={styles.errorMessage}>{err.message}</Text></View> : null}
<CheckinModal
ref={modalRef}
businessName={modalState.companyName}
address={modalState.companyAddress}
waitTime={modalState.waitTime}
/>
</View>
);
};
Run Code Online (Sandbox Code Playgroud)
地图
const Map = ({markers}, ref) => {
const {state: {currentLocation}} = useContext(Context);
return (
<MapView
style={styles.map}
provider={PROVIDER_GOOGLE}
initialRegion={{
...currentLocation.coords,
latitudeDelta: regions.latDelta,
longitudeDelta: regions.longDelta
}}
showsUserLocation
>
{markers ? markers.map((marker, index) => {
return marker;
}): null}
</MapView>
)
};
export default Map;
Run Code Online (Sandbox Code Playgroud)
签到模态
const CheckinModal = ({businessName, address, waitTime}, ref) => {
return (
<ModalBox
style={styles.modal}
position={'bottom'}
backdrop={true}
ref={ref}
>
<Text>Store Name: {businessName}</Text>
<Text>Store Address: {address}</Text>
<Text>Wait time: {waitTime} minutes</Text>
</ModalBox>
)
};
const forwardModal = React.forwardRef(CheckinModal);
export default forwardModal;
Run Code Online (Sandbox Code Playgroud)
位置标记
const LocationMarker = (props) => {
return (
<View>
<Marker
coordinate={props.coordinate}
title={props.title}
id={props.id}
onPress={() => {
props.onShowModal();
}}
>
<Image
source={require('../../assets/marker2.png')}
style={styles.locationMarker}/>
<View style={styles.waitContainer}>
<Text style={styles.waitText}>{props.waitTime}</Text>
</View>
</Marker>
</View>
)
};
export default LocationMarker;
Run Code Online (Sandbox Code Playgroud)
使用这个新代码,我不必转发太多引用,只需转发到CheckinModal。
如果有人有任何问题,请在此答案下方留言,我会尽快回答。感谢大家的帮助。
| 归档时间: |
|
| 查看次数: |
116 次 |
| 最近记录: |