0

I am currently working on a school project. I have a map location app. But somehow I need to pass state value coordinates. But I can't share it into the next class... Can someone help me out?

Code:

import React from 'react';
import '../style/card.css';
import '../js/functions/maps';
import Button from './button.js';
import { getLocation } from './functions/getLocation.js';
import './functions/maps';



class Mobile extends React.Component {
  state = {
    coordinates: {}
  };

  getLocationCoordinates = () => {
    getLocation((coordinates) => {
      this.setState({ coordinates });
      console.log(this.state.coordinates);
    });
  };

  functionCoordinatePrint = (index) => {
    return this.state.coordinates[index] ? this.state.coordinates[index] : Math.random() * 50 + 1;
  };

  render() {
    const { lat, lng } = this.state.coordinates;
    return (
      <div id={'location'} className={'card'}>
        <div className={'card-layout'}>
          <div className={'text-card'}>
            <h1>{this.props.header}</h1>
            {this.props.text !== '' && <p className={'max-width-70'}>{this.props.text}</p>}
            <div
              style={{
                color: 'var(--color-text)'
              }}
            >
              <input type="checkbox" id="conditions-read" />
              <a href="../pages/algemene-voorwaarden">Accepteer voorwaarden</a>
            </div>

            <Button function={this.getLocationCoordinates} text={'Allow Location'} />
            <p>{this.props.coordinaten}</p>
          </div>
          <div className={'mobile'}>
            <img src={this.props.device} className={'device'} alt={this.props.alt_image} />
            <div className={'overlay'}>
              <div id={'location-maps'}>
                <iframe
                  title="map"
                  frameBorder="0"
                  scrolling="no"
                  marginHeight="0"
                  marginWidth="0"
                  src={`https://www.mapquest.com/near-${this.functionCoordinatePrint(
                    'latitude'
                  )},${this.functionCoordinatePrint('longitude')}?zoom=3`}
                />
              </div>
            </div>
          </div>
        </div>
      </div>
    );
  }
  coordinatesToArray = coordinatesToArray[
    (this.functionCoordinatePrint('latitude'), this.functionCoordinatePrint('longitude'))
  ];
}

class Laptop extends React.Component {
  render() {
    return (
      <div id={'recommendations'} className={'card'}>
        <div className={'card-layout'}>
          <h1>{this.props.header}</h1>

          <div className={'laptop'}>
            <img
              style={{
                width: '150%'
              }}
              src={this.props.device}
              alt={this.props.alt}
            />
            <div className={'overlay-laptop'}>
              <div className={'maps'}>
                <iframe
                  title="mapExample"
                  frameBorder="0"
                  scrolling="no"
                  marginHeight="0"
                  marginWidth="0"
                  src={
                    'https://www.mapquest.com/near-' +
                    (this.props.lat ? this.props.lat : Math.random() * 30 + 1) +
                    ',' +
                    (this.props.long ? this.props.long : Math.random() * 30 + 1) +
                    '?zoom=3'
                  }
                />
              </div>
            </div>
          </div>
        </div>
      </div>
    );
  }
}

export { Mobile, Laptop };

I've tried to use props.state.coordinates[0], I also used a global var and have set the values in function GetLocation() and then use it into my Laptop version. But can someone help me?

Thanks in advance.

abhikumar22
  • 1,764
  • 2
  • 11
  • 24
Valdemar Vreeman
  • 177
  • 2
  • 16
  • Can you improve your answer by adding this information: 1. the structures of the components 2. the component containing the state 3. the component the need to use the state. – Stoic Lion May 25 '20 at 13:52
  • @SorcererApprentice these are my cards. In my App.js I include these Laptop and Mobile versions. Mobile has mobile png and laptop has a laptop png. with a map location in each other. But in the mobile card you give access for location. then you get long and latitude – Valdemar Vreeman May 25 '20 at 14:12
  • Which class do you want to pass the data into? you could simply do and then in `MyComponent` you can access it as `this.props.data`. Or am I missing something? – ABGR May 25 '20 at 14:20
  • @RahulDwivedi I have data in Mobile Component and not in App(global Component), because I want button in Mobile Component which access the location and then add values in Laptop Component – Valdemar Vreeman May 25 '20 at 14:31
  • So, you just want to pass your location info into your `laptop` component if I understand correctly? – ABGR May 25 '20 at 14:37
  • @RahulDwivedi yea correct – Valdemar Vreeman May 25 '20 at 14:41
  • I have an answer to a similar question here: https://stackoverflow.com/a/51661103/2430549 "Correct way to share functions between components in React", of course, you just need a getState() function and to share that. – HoldOffHunger May 25 '20 at 14:43

3 Answers3

1
  1. First separate the the two components, mobile and laptop into separate files. They have their own states to manage and by doing so, you code will be more manageable. then
  2. Import Laptop component into mobile component.
  3. Pass the data into laptop component, for e.g, <Laptop data={this.state.coordinates}/>

  4. Inside your Laptop component get this information with, this.props.data

ABGR
  • 4,631
  • 4
  • 27
  • 49
  • Is this a clean way to do it? – Valdemar Vreeman May 25 '20 at 18:08
  • Yes of course. You want to pass data from `mobile` to `laptop` component.So you should separate them into and pass accordingly. – ABGR May 25 '20 at 18:10
  • Yea but you probably also can do the "lifting state up" option or not? – Valdemar Vreeman May 25 '20 at 18:10
  • @user12380607 That is advisable when both `laptop` and `mobile` are receiving data from a single component. However, in this case, `mobile` is responsible for sending data into `laptop` component. – ABGR May 25 '20 at 18:16
  • I think I should clean up my code a bit... I should make a function with button and I include that in Mobile, but the data goes to the App Component – Valdemar Vreeman May 25 '20 at 18:29
  • Your `App` component is at the top of the hierarchy. So ideally, that shouldn't come into the picture when you just want to play around passing data from `mobile` to `laptop`. – ABGR May 25 '20 at 18:34
  • So you've to make the App component the most important one. Which comes all the data from? – Valdemar Vreeman May 25 '20 at 19:56
  • You can think of it as the one which finally assimilates all of the components together. For e.g App renders Mobile which in turns renders laptop plus two other components. So finally all of them are in a way children/grand-children of this root component. – ABGR May 25 '20 at 20:00
0

Easiest way would be simply passing the data down through props. If Laptop and Mobile are siblings then you will need to "lift state up" to a common parent component, then you can manage the state in there and pass it down to each of the children using props e.g.

<Mobile myState={myStateVariable} /> <Laptop myState={myStateVariable} />

lsdmt
  • 160
  • 1
  • 7
  • But my values are in mobile Component instead of App component – Valdemar Vreeman May 25 '20 at 14:24
  • It says this.props.functionCoordinatesPrint is not a function – Valdemar Vreeman May 25 '20 at 14:42
  • Either you need to make one a child of the other so you can pass in props to the child one or you need to lift your values up to a parent component and pass in the values and functions to your child components. See this for reference https://reactjs.org/docs/lifting-state-up.html. Alternatively you can use context or a state framework such as redux and then you can manage your state in those and any component can use it. – lsdmt May 25 '20 at 17:31
0

What might help you in this case is a Higher Order Component, or HOC for short. You can see a HOC as a parent component where you can store the coordinates. The child components (in your case Mobile and Laptop) can than set and access the data in the HOC allowing the child components to render the coordinates.

Lets clarify this in more detail. First you need to create a HOC component that keeps the coordinates in its state. The HOC should have a setter that needs to be passed to the child components as a property. The value of the coordinates should also be passed to the child components, which we can do using the spread operator.

const withCoordinates = (WrappedComponent) => {
    class WithCoordinates extends Component {
        constructor(props) {
            super(props);
            this.state = {
              coordinates: [],
            };
          }

          setCoordinates = (event) => {
            const { name, value } = e.target;
            this.setState({ [name]: value });    
          }

          render() {
              return (
                    <WrappedComponent
                      setCoordinates={(coordinates) => this.setCoordinates(coordinates)}
                      {...this.state}
                    />
              );
          }
    }

    return WithCoordinates;
}

export default withCoordinates;

Next we need to hook the child components up so it can access the values defined the HOC. Since we passed the coordinates value and the setCoordinates method through the properties we can access them in the child component.

class Laptop extends Component {
    render() {
        const { setCoordinates, coordinates } = this.props;

        return (
            <>
                <input name='coordinates' value={coordinates || ''} onChange={(e) => setCoordinates(e)} />
                <p>The coordinates are {coordinates}</p>
            </>
        );
    }
}

export default WithCoordinates(Laptop);

Notice that the child component is exported along with the WithCoordinates component wrapped around it. This makes it possible for the child component to access the values in the HOC. The name of the input field in the child component corresponds to the state value that is being set in the HOC.

Do not forget to validate the props by using the Proptypes library.

Mitch
  • 715
  • 4
  • 12
  • 28