How can I pass data from a functional comp to a class comp?

This is so difficult to get my head around… I just want to pass data from a functional component to a class component, how can I do this?

my first parent component that has the data is a modal and then my child class component is a form inside the modal

Hello there,

It would be a lot easier to help, if you posted a link to your code, or pasted the relevant code here.

Here is my parent modal:

import React, { useState, useEffect, setState } from 'react';
import { View, Text, StyleSheet, Modal } from 'react-native';
import { MaterialIcons } from "@expo/vector-icons"
import AddReportForm from "./AddReportForm";
import * as Location from 'expo-location';
import { LOCATION } from 'expo-permissions';


export default function AddReportModal() {
    const [location, setLocation] = useState(null);
    const [errorMsg, setErrorMsg] = useState(null);
    const [modalOpen, setModalOpen] = useState(false)
    state = { location: {} }
    useEffect(() => {
        (async () => {
            let { status } = await Location.requestPermissionsAsync();
            if (status !== 'granted') {
                setErrorMsg('Permission to access location was denied');
            }

            let location = await Location.getCurrentPositionAsync({});
            setLocation(location);
        })();
    });

    let latitude = 'Waiting..';
    let longitude = 'Waiting..';
    if (errorMsg) {
        text = errorMsg;
    } else if (location) {
        latitude = JSON.stringify(location.coords.latitude);
        longitude = JSON.stringify(location.coords.longitude);
        // console.log(location.coords.latitude)
        setState({ location: location })
    }

    return (
        <View>
            <MaterialIcons
                name='add'
                size={34}
                onPress={() => setModalOpen(true)}
                style={styles.modalToggle}
            />

            <Modal visible={modalOpen} animationType='slide' dataFromParent={this.state.location}>
                <View style={styles.modalContent}>
                    <MaterialIcons
                        name='close'
                        size={34}
                        onPress={() => setModalOpen(false)}
                        style={{ ...styles.modalToggle, ...styles.modalClose }}
                    />
                    <Text style={styles.modalText}>{latitude}</Text>
                    <Text style={styles.modalText}>{longitude}</Text>
                    <AddReportForm />
                </View>
            </Modal>
        </View>
    );
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        alignItems: 'center',
        justifyContent: 'center'
    },
    modalToggle: {
        marginBottom: 10,
        borderWidth: 1,
        borderColor: '#f2f2f2',
        padding: 10,
        borderRadius: 10,
        alignSelf: 'center'
    },
    modalClose: {
        marginTop: 20,
        marginBottom: 0
    },
    modalContent: {
        flex: 1
    },
    modalText: {
        color: '#999'
    }
})

Here is my child form inside my modal:

import React, { useState, useEffect } from 'react';
import { View, Text, StyleSheet, Button, TextInput, Platform } from 'react-native';
import { Formik } from 'formik';


export default class AddReportForm extends React.Component {
    constructor(props) {
        super(props);
        state = {
            location: {},
            errorMessage: ''
        }
    }

    render() {
        return (
            <View style={styles.container}>
                <Formik
                    initialValues={{ name: '', latitude: '', longitude: '', read: false, saved: false }}
                    onSubmit={(values) => {
                        console.log(values)
                    }}
                >
                    {(props) => (
                        <View>
                            <TextInput
                                multiline
                                style={styles.input}
                                placeholder='Name'
                                onChangeText={props.handleChange('name')}
                                value={props.values.name}
                            />

                            <TextInput
                                style={styles.input}
                                placeholder='Latitude'
                                onChangeText={props.handleChange('latitude')}
                                value={props.values.latitude}
                            />

                            <TextInput
                                style={styles.input}
                                placeholder='Longitude'
                                onChangeText={props.handleChange('longitude')}
                                value={props.values.longitude}
                            />
                            <Button
                                title='Submit' color='maroon' onPress={props.handleSubmit}
                            />
                            <Text>{this.props.dataFromParent}</Text>
                        </View>
                    )}
                </Formik>
                <Text>{JSON.stringify(this.state.location)}</Text>
            </View>
        );
    }
}


const styles = StyleSheet.create({
    container: {
        flex: 1
    },
    input: {
        borderWidth: 1,
        borderColor: '#ddd',
        padding: 10,
        fontSize: 18,
        borderRadius: 6
    }
})

Now I’m getting a problem where I am trying to setState in my parent component

Thank you, for posting that.

Now, what data are you wanting to pass to AddReportForm? Is there any reason you cannot use props?

I am not sure where you are getting these props from:

<TextInput
                                multiline
                                style={styles.input}
                                placeholder='Name'
                                onChangeText={props.handleChange('name')}
                                value={props.values.name}
                            />

As, when you call the component, you do not pass any to it:
<AddReportForm />

this is so difficult…

ok great, it is working, I am now passing them through to the form but the form values are not being set when I pass the props into them…

so now I am trying to set the state and pull the values from the state

constructor(props) {
        super(props);
        this.setState({ latitude: this.props.latitude })
        this.setState({ longitude: this.props.longitude })
        state = {
            location: {},
            latitude: 0,
            longitude: 0,
            errorMessage: ''
        }
    }

I am getting:

TypeError: null is not an object (evaluating ‘_this2.state.latitude’)

and here is where it is erroring:

<Formik
                    initialValues={{ name: '', latitude: 0, longitude: 0, read: false, saved: false }}
                    onSubmit={(values) => {
                        console.log(values)
                    }}
                >
                    {(props) => (
                        <View>
                            <TextInput
                                multiline
                                style={styles.input}
                                placeholder='Name'
                                onChangeText={props.handleChange('name')}
                                value={props.values.name}
                            />

                            <TextInput
                                style={styles.input}
                                placeholder='Latitude'
                                onChangeText={props.handleChange('latitude')}
                                value={this.state.latitude}
                            />

                            <TextInput
                                style={styles.input}
                                placeholder='Longitude'
                                onChangeText={props.handleChange('longitude')}
                                value={this.state.longitude}
                            />
                            <Button
                                title='Submit' color='maroon' onPress={props.handleSubmit}
                            />
                        </View>
                    )}
                </Formik>

Why aren’t you just using the props?

  • Don’t use setState in the constructor
  • Don’t clone props to state, it’s a huge antipattern that makes it incredibly easy to cause bugs and makes things super complicated. There is the UNSAFE_componentWillReceiveProps() method, but as the name suggests is not something you probably want to be using.

I don’t quite understand why you don’t just use a function component, you gain nothing using a class component here (or why you don’t just use class components, the obverse is true)

ok great thanks…

So, I am passing the Latitude and Longitude to my form fields great!
Here is my next problem:

I am using Formik and I’m setting initial values to ‘0’

<Formik
                    initialValues={{ name: '', latitude: 0, longitude: 0, read: false, saved: false }}
                    onSubmit={(values) => {
                        console.log(values)
                    }}
                >
                    {(props) => (
                        <View>
                            <TextInput
                                multiline
                                style={styles.input}
                                placeholder='Name'
                                onChangeText={props.handleChange('name')}
                                value={props.values.name}
                            />

                            <TextInput
                                style={styles.input}
                                placeholder='Latitude'
                                onChangeText={props.handleChange('latitude')}
                                value={this.props.latitude}
                            />

                            <TextInput
                                style={styles.input}
                                placeholder='Longitude'
                                onChangeText={props.handleChange('longitude')}
                                value={this.props.longitude}
                            />
                            <Button
                                title='Submit' color='maroon' onPress={props.handleSubmit}
                            />
                        </View>
                    )}
                </Formik>

when I submit my form, I get the following:

Object {
“latitude”: 0,
“longitude”: 0,
“name”: “Test”,
“read”: false,
“saved”: false,
}

Why are they set to 0?

Now what you’re doing is setting the values from the props of the parent component. I assume there isn’t a prop “longitude” or “latitude” so these never get changed from the initial value. It should be props.values.longitude

Note that giving unconnected things with drastically different functionality the same names is a bad idea, don’t call the Formik object props