Button to load new screen but staying on one page - reactjs

Okay so I am trying to accomplish what these photos show. I want to be able to go from list, which is a view with a white background that has some content to when clicked on map, it does not necessarily change pages, but it does load this screen of a map.
What is the best way to go about doing this for react native? I tried googling around but could not find much, it was hard to google for.
Thank you guys, I appreciate it more than you know.

I think you may be asking about how to conditionally render something. You can render components based on the value of another variable. Something like this.
const [viewMode, setViewMode] = useState('list');
const handleShowListPress = () => {
setViewMode('list');
};
const handleShowMapPress = () => {
setViewMode('map');
};
...
return (
<View>
<ListButton onPress={handleShowListPress} />
<MapButton onPress={handleShowMapPress} />
{viewMode === 'list' && <ListView />}
{viewMode === 'map' && <MapView />}
</View>
);

Related

React scroll to element (ref current is null) problem

I have a problem I'm not able to solve. The app got a component where a do looping array and making multiple elements off it. Then I want to make buttons in another component that will scroll to a specific element. (something similar to liveuamap.com when you click on a circle).
I tried the below solution, but got "Uncaught TypeError: props.refs is undefined". I could not find any solution to fix it.
The second question: is there a better or different solution to make scrolling work?
In app component I creating refs and function for scrolling:
const refs = DUMMY_DATA.reduce((acc, value) => {
acc[value.id] = React.createRef();
return acc;
}, {});
const handleClick = (id) => {
console.log(refs);
refs[id].current.scrollIntoView({
behavior: "smooth",
block: "start",
});
};
The refs I send to the article component as a prop where I render elements with generated refs from the app component.
{props.data.map((article) => (
<ContentArticlesCard
key={article.id}
ref={props.refs[article.id]}
data={article}
onActiveArticle={props.onActiveArticle}
activeArticle={props.activeArticle}
/>
))}
The function is sent to another component as a prop where I create buttons from the same data with added function to scroll to a specific item in the article component.
{props.data.map((marker) => (
<Marker
position={[marker.location.lat, marker.location.lng]}
icon={
props.activeArticle === marker.id ? iconCircleActive : iconCircle
}
key={marker.id}
eventHandlers={{
click: () => {
props.onActiveArticle(marker.id);
// props.handleClick(marker.id);
},
}}
></Marker>
))}
Thanks for the answers.
Ok so i found the solution in library react-scroll with easy scroll implementation.

Why is my React Native component not re-rendering on state update?

I'm struggling with this React-Native component for a few days now. You should probably know that React-Native is kind of new to me so... sorry if the solution is obvious to you.
I'm using react-native-maps and I have several markers on my map. Each one of them has some data stored in my state and I want the callout to display a piece of this state on press.
Here are my states :
const [markersDetails, setMarkersDetails] = useState([]);
const [activeMarker, setActiveMarker] = useState({});
My activeMarker is updated by this function :
const markerSearch = (markerId) => {
let stockMarker = markersDetails.find((singleMarker) => {
return Number(singleMarker.idMarker) === markerId;
});
console.log("Stock ", stockMarker);
setActiveMarker(stockMarker);
console.log("State ", activeMarker);
};
And this function is called, inside my return, with the onPress of any marker :
<Marker
key={Number(marker.index)}
coordinate={{
latitude: Number(marker.latitude),
longitude: Number(marker.longitude),
}}
pinColor="blue"
onPress={() => {
markerSearch(Number(marker.index));
}}
>
{activeMarker !== {} && activeMarker.markerName && (
<Callout>
<View>
<Text>{activeMarker.markerName}</Text>
</View>
</Callout>
)}
</Marker>
But whenever I press on a marker, the callout opens immediatly while my state is not yet updated. So the text within the callout refers either to the previous marker or is empty (if it's the first marker I press on).
I've checked with console.log and my state is clearly updated but it takes a little bit more time. And I don't know why my callout is not re-rendering when this state is updating.
I've tried a ton of things to make this works but I can't figure this out...
Try doing something like that:
You can extract the section to a new component
Then inside this use the useEffect hook
export default function CalloutComponent({activeMarker}) {
const [markerName, setMarkerName] = useState('')
useEffect(() => {
setMarkerName(activeMarker?.markerName)
}, [activeMarker?.markerName])
if(!!markerName) return null
return (
<Callout>
<View>
<Text>{markerName}</Text>
</View>
</Callout>
)
}
And use this new component in your Main view
<Marker
...
>
<CalloutComponent activeMarker={activeMarker}/>
</Marker>

How to pass parameters to another screen without navigating to it

Right now to pass parameters to another screen I'm using the following:
this.props.navigation.navigate('MyWatchList', {watchLists: response});
This automatically navigates to the other screen. I'm trying to pass parameters to another screen without navigating away from the screen I'm on but I'm having trouble figuring out how to do it. I have been trying to use setParams but I have been having no success. Any help or a point in the right direction would be appreciated.
You can consider to use the asyncStorage in order to share data between your screens.
e.g
AsyncStorage.setItem('MyWatchList',JSON.stringify({watchLists: response}));
and retrieve by using
AsyncStorage.getItem('MyWatchList').then(item => {
const list = JSON.parse(item);
...
});
You can also use EventRegister
import { EventRegister } from "react-native-event-listeners";
send value like this:
<TouchableOpacity
onPress={() => {this.setState({ visibleModal: false });
EventRegister.emit("changeModalEvent", this.state.visibleModal);
}}
>
{this.state.theme == true ? (
<Icon3 name="cancel" color={Colors.night_color_text} size={30} />
) : (
<Image
source={require("../assets/images/Auto_Layout_Horizontal.png")}
style={{ height: 24, width: 24 }}
/>
)}
</TouchableOpacity>
read the value in any screen with respect to the key like this:
useEffect(() => {
let eventListner = EventRegister.addEventListener(
"changeModalEvent",
(data) => {
// console.log({ data });
setVisibleModal(data);
}
);
return () => {
EventRegister.removeEventListener(eventListner)
};
});
what i think you trying to achieve is persistent state across screen you can do that by multiple of ways
you can use global variable you will be able to read and write to them from all of your classes/functions read more here
How to use global variables in React Native?
But the most effective way is to use redux to mange your state
Redux is an open-source JavaScript library for managing and
centralizing application state.
You can Store Your Data in Array and when you navigate to next screen , Pass that Array with navigation

useEffect not cleaning up after redirect

Let me explain my problem I have been solving for all day.
I have a site with header which has of course by react-router links to other pages (home, projects, about, services, contact).
Have a Project component which is in '/projects' page and '/' (home) page.
I want to make a simple animation in Project.js component which depends if there is a 'vertical' or there is not this props. Clearly -> in '/projects' I want to do that animation on scroll - in other pages not.
Tried to do that by add if statement in useEffect but it's not working, get me an error 'cannot read property 'style' of null ref.current.style.transform = `translateY(${window.scrollY * -0.35}px)`;
This problem is showing up when I am changing pages in header i.eg. I am in '/projects' scrolling and is ok animation is working then go to '/' and when scroll got error I have showed above.
It is like my if statement is not working and when I am in '/' which Project component has props vertical={false} is making animation on scroll when I don't want to do that.
What I want? I want do make an animation using useEffect only if component has a props 'vertical' like this:
Project.js component code:
const Project = ({ image, className, vertical }) => {
const ref = useRef(null);
const [isVertical, setIsVertical] = useState(vertical);
useEffect(() => {
console.log('component did mount');
isVertical
? window.addEventListener('scroll', () => {
ref.current.style.transform = `translateY(${window.scrollY * -0.35}px)`;
})
: console.log('non-vertical');
}, [isVertical]);
useEffect(() => {
return () => console.log('unmount');
});
return <StyledProject image={image} className={className} vertical={vertical} ref={ref} />;
};
in home '/':
{images.map(({ image, id }) => (
<Project key={id} image={image} />
))}
in '/projects':
{images.map(({ image, id }) => (
<StyledProject vertical image={image} key={id} />
))}
when I am in the path '/projects' and go to another path got error.
It is like after being in '/projects' it is saving all statements was but I want on every page reset useEffect and ref.current
Please help me, I can't go further since I don't fix this.
Thanks in advance.
Main problem is that you are not removing event listener when component unmounts.
Here you can see an example how to do it.

How to initiate a render when Flatlist content is less to have a scroll - React Native

I am trying to do a filtered infinite scroll, I am using a flatlist for that. The items are of variable height. If the fetched list has only one item or no item, onEndReached does not get triggered because there is no scroll. So, I cannot fetch new items. Any solution for this?
class Vehicle extends Component{
loadMoreVehicles = () =>this.props.vehicleActions.fetchMoreVehicles
(this.state.page);
renderItem = ({ item,index }) => {
return (this.filterVehicle(item))? <VehicleList item ={item}/>:null
}
render(){
<VehicleView vehicles ={this.props.vehicles}/>
}
}
const VehicleView =(props)=>(
<FlatList data={props.vehicles}
keyExtractor={(item, index) => index}
onEndReached={props.loadMoreVehicles}
onEndThreshold={100}
removeClippedSubviews={false}
renderItem={props.renderItem}
initialNumToRender={10}
extra={props}
windowSize={10} />
)
this.filterVehicle(item) would return true/false on whether the item is to be shown or not.
Thanks in advance
It would have been better if you provided more detail with relevant code snippets. But still from what I have understood, it seems that you want to dynamically set the scrolling behavior of FlatList depending upon the content size. You can use onContentSizeChange prop for that. A very good article is available on medium on how to actually implement it.

Resources