0

I'm a newbie to React and I'm having trouble with calling functions between components. I've been looking for weeks on a solution but can't seem to crack it. I've been reading that the right way to do it is through the parent/child relationship.

However, in this circumstance I can't seem to form that structure.

Basically, I'm using google maps and can auto move the map to a Marker when clicked on it (using the animateToRegion function). I also have a search bar in the NavBar that lists locations. When I pick a location in that search, I would like the map to move to that location. Pretty straight forward.

Since the Map component and the Search component are separate I can't send the information to the animateToRegion function.

My main question would be: Is there a way to form a relationship with two components that seem to have no connection? Is the parent/child the only way for this to work?

Any help would be very much appreciated. Thank you.

Below is the main Map component. I've trimmed down the unnecessary stuff. The main things to look at are the onPress={} functions.


import React, { Component, useEffect, useState, useRef } from "react";

const initialRegion = {
  latitude: 53.3441204,
  longitude: -6.26298,
  latitudeDelta: 0.015,
  longitudeDelta: 0.0121,
};



const MapData = (props) => {

  const mapRef = useRef();
  useDispatch(map_ref(mapRef));
  const [stationData, setStationData] = useState([]);
  const [singleStation, setSingleStation] = useState("");

  useEffect(() => {
    API().then((result) => setStationData(result));
  }, []);


  return (
    <View>
      <MapView
        ref={mapRef}
        initialRegion={initialRegion}
      >
        {stationData.map((station) => {
          return (
            <View key={station.position.lat}>
              <Marker
                key={station.name}
                coordinate={{
                  latitude: station.position.lat,
                  longitude: station.position.lng,
                }}
                onPress={() => {
                  animateToRegion(
                    station.position.lat,
                    station.position.lng,
                    mapRef
                  );
                }}
              >
              </Marker>
            </View>
          );
        })}
      </MapView>
    </View>
  );
};

export default MapData;

This is the Animate to Reagion Component that I would like the Map and Search components to use.

const animateToRegion = (lat, lng, mapRef) => {
  mapRef.current.animateToRegion(
    {
      latitude: lat,
      longitude: lng,
      latitudeDelta: 0.01,
      longitudeDelta: 0.0121,
    },
    1000
  );
};

export default animateToRegion;

This is the Search function. I've tried using the ref hook, but I'm going in circles

import React, { useEffect, useRef, useState } from "react";
import animateToRegion from "./animateToRegion";


const Search= () => {
  const [options, setOptions] = useState([]);
  const [search, setSearch] = useState("");
  const [display, setDisplay] = useState(true);

  useEffect(() => {
    API().then((result) => setOptions(result));
  }, []);

  // const autoRef = useRef(null);

  // const automove;
  const mapRef = useRef();

  return (
    <View
    >
      <TextInput
        multiline={true}
        placeholder="Enter Station..."
        value={search}
      />

      {display && (
        <ScrollView
          keyboardShouldPersistTaps="handled"
        >
          {options.map((station) => {
            return (
              <View
                key={station.position.lat}
              >
                <TouchableOpacity
                  onPress={() => animateToRegion(station.position.lat, station.position.lng, mapRef)}
                >
                  <View>
                    <Text>{station.name}</Text>
                    <Text>{station.available_bikes}</Text>
                  </View>
                </TouchableOpacity>
              </View>
            );
          })}
        </ScrollView>
      )}
    </View>
  );
};

export default Search;

  • You can always import function from one file to another. So assuming you want to transfer values from file1 to file2, just create a function that return the value you need. https://stackoverflow.com/questions/54199264/how-can-i-use-a-function-from-another-file-in-react/54199395 – Yotam Dahan Apr 01 '21 at 11:21
  • You can do as @YotamDahan says or using the parent component: You create your function in the parent component and you pass it as props in your two child components. – MB_ Apr 01 '21 at 11:26
  • Thanks for the replys. I think my issue is the overall structure. There's a whole navigation section going on in the back. I can't form a parent/child relationship in the circumstance. Sorry, I should have said this is a React Native app. – Dean Lauder Apr 01 '21 at 11:35

1 Answers1

0

In your search function component you define a new ref and pass this as a parameter to your animateToRegion function. Therefore when you call mapRef.current.animateToRegion in that function it is not referring to the same ref as the one in your <MapView> component in MapData.

However I don't think refs where meant to be used across components in such a fashion (https://reactjs.org/docs/forwarding-refs.html#forwarding-refs-in-higher-order-components).

think my issue is the overall structure. There's a whole navigation section going on in the back. I can't form a parent/child relationship in the circumstance.

Is there a good reason why your search bar and your map would be separate from one another? If they are to be displayed on the same screen, surely it would make sense for both of them to be children of that component?

My main question would be: Is there a way to form a relationship with two components that seem to have no connection? Is the parent/child the only way for this to work?

You could look into redux for having a state wide application, to and from which any component can have access (looks like you might already have it setup given the useDispatch hook).

Alternatively you can look into custom events and event listeners, so when a user picks a region from the search you emit an event with the lat and lng as parameters, and have an event listener for this event in your MapData component.

Oskar
  • 346
  • 1
  • 3