I’m encountering an issue with sending data from my React Native frontend to a backend endpoint. I’ve provided the relevant code snippets below.I’m encountering an issue with sending data from my React Native frontend to a backend endpoint (/onboarding/v3). Below, I’ve provided relevant code snippets and additional details about my setup.
User Model:
I’m using a MongoDB database with Mongoose to define my user schema. The schema includes fields for name, email, password, and various other user details. Of particular relevance to this issue is the areasOfInterest field, which is an array of objects containing title and items properties.
I have a React Native component AreasOfInterest where users select their areas of interest and rate their expertise. Upon pressing a “Next” button, I want to send this data to the backend.
I would appreciate any guidance on how to properly format the data and resolve the issue with sending it to the backend endpoint. I’ve included relevant code snippets below for reference.
Backend Endpoint:
I have a backend endpoint /onboarding/v3
Please fix my code
My User Model is below. after it
const mongoose = require("mongoose");
// Define schema for items within an area of interest
const InterestItemSchema = new mongoose.Schema({
name: {
type: String,
required: true,
},
stars: {
type: Number,
min: 1,
max: 5,
default: 1, // Default to 1 star
},
});
// Define schema for areas of interest
const InterestSchema = new mongoose.Schema({
title: {
type: String,
required: true,
},
items: {
type: [InterestItemSchema],
default: [],
},
});
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
image: {
type: String,
required: true,
},
friendRequests: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
],
friends: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
],
sentFriendRequests: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
],
First_Name: {
type: String,
default: "",
},
Last_Name: {
type: String,
default: "",
},
Pronoun: {
type: String,
default: "",
},
Gender: {
type: String,
default: "",
},
Race: {
type: String,
default: "",
},
Country: {
type: String,
default: "",
},
State: {
type: String,
default: "",
},
City: {
type: String,
default: "",
},
Role: {
type: String,
default: "",
},
Student: {
type: Boolean,
default: false,
},
Mentor: {
type: Boolean,
default: false,
},
Affiliation: {
type: String,
default: "",
},
Headline: {
type: String,
default: "",
},
Education: {
type: String,
default: "",
},
Major: {
type: String,
default: "",
},
Degree: {
type: String,
default: "",
},
GradeYear: {
type: String,
default: "",
},
areasOfInterest: {
type: [InterestSchema],
default: [],
},
Career_Goals: {
type: [String],
default: [],
},
withOrgOnly: {
type: Boolean,
default: false,
},
createdAt: {
type: Date,
default: Date.now,
},
updatedAt: {
type: Date,
default: Date.now,
},
});
const User = mongoose.model("User", userSchema);
module.exports = User;
// Backend Endpoint (Working (not sure about onboarding/v3) )
const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const passport = require("passport");
const LocalStrategy = require("passport-local").Strategy;
const bcrypt = require("bcrypt");
const os = require("os");
const app = express();
const morgan = require("morgan");
const port = 8080;
const cors = require("cors");
const router = express.Router();
app.use(morgan("dev"));
app.use(cors());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(passport.initialize());
const jwt = require("jsonwebtoken");
const User = require("./models/user");
// POST endpoint for onboarding/v3
app.post("/onboarding/v3", async (req, res) => {
try {
const { userId, areasOfInterest } = req.body;
const user = await User.findById(userId);
console.log(user.name);
console.log(areasOfInterest);
if (!user) {
return res.status(404).json({ message: "User not found" });
}
user.areasOfInterest = areasOfInterest;
await user.save();
res.status(200).json({ message: "Areas of interest updated successfully" });
} catch (err) {
console.log("Error updating areas of interest", err);
res.status(500).json({ message: "Error updating areas of interest" });
}
});
// Frontend Main Page.
import React, { useState, useContext } from "react";
import {
View,
Text,
SafeAreaView,
TextInput,
TouchableOpacity,
FlatList,
} from "react-native";
import Icon from "react-native-vector-icons/FontAwesome5";
import { CheckBox } from "react-native-elements";
import { AntDesign } from "@expo/vector-icons";
import axios from "axios";
import { UserType } from "../../UserContext";
const NavigationLine = ({ active }) => (
<View
style={{
flex: 1,
height: 5,
backgroundColor: active ? "#57D5DB" : "#DBD4D4",
marginHorizontal: 5,
}}
/>
);
const InterestList = ({ data }) => {
const [expanded, setExpanded] = useState(false);
const [ratings, setRatings] = useState(Array(data.items.length).fill(0));
const [selectedItems, setSelectedItems] = useState(
Array(data.items.length).fill(false)
);
const handleRatingChange = (index, rating) => {
const newRatings = [...ratings];
newRatings[index] = rating;
setRatings(newRatings);
};
const toggleCheckbox = (index) => {
const newSelectedItems = [...selectedItems];
newSelectedItems[index] = !selectedItems[index];
setSelectedItems(newSelectedItems);
// Reset rating to 0 when unchecking the checkbox
if (!newSelectedItems[index]) {
handleRatingChange(index, 0);
}
};
return (
<View>
<TouchableOpacity
onPress={() => setExpanded(!expanded)}
style={{
flexDirection: "row",
alignItems: "center",
backgroundColor: "#F1F1F3",
width: "90%",
height: 50,
borderRadius: 20,
marginTop: 15,
paddingHorizontal: 20,
borderColor: "#D9D9D9",
borderWidth: 1,
marginHorizontal: 15,
}}
>
<Icon
name={expanded ? "caret-down" : "caret-right"}
size={15}
color="#9C9C9C"
/>
<Text style={{ flex: 1, marginLeft: 10 }}>{data.title}</Text>
</TouchableOpacity>
{expanded && (
<FlatList
data={data.items}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item, index }) => (
<View
style={{
flexDirection: "row",
alignItems: "center",
backgroundColor: "#F1F1F3",
width: "90%",
height: 50,
borderRadius: 20,
marginTop: 5,
marginHorizontal: 15,
borderWidth: 0.1,
}}
>
<TouchableOpacity
onPress={() => toggleCheckbox(index)}
style={{ marginLeft: 20, marginRight: 10 }}
>
<Icon
name={selectedItems[index] ? "check-square" : "square"}
size={20}
color="#000"
/>
</TouchableOpacity>
<View style={{ flex: 1 }}>
<Text style={{ fontSize: 13 }}>{item}</Text>
</View>
{selectedItems[index] && ( // Show stars only if checkbox is selected
<View style={{ flexDirection: "row", marginRight: 20 }}>
{[1, 2, 3, 4, 5].map((star) => (
<TouchableOpacity
key={star}
onPress={() => handleRatingChange(index, star)}
style={{ marginRight: 4 }}
>
<AntDesign
name="star"
size={20}
color={ratings[index] >= star ? "#FFD700" : "#D3D3D3"}
/>
</TouchableOpacity>
))}
</View>
)}
</View>
)}
/>
)}
</View>
);
};
const AreasOfInterest = ({ navigation }) => {
// Use userId to send backend
const { userId, setUserId } = useContext(UserType);
const interestData = [
{
title: "Accounting",
items: [
"Financial Accounting",
"Cost Accounting",
"Managerial Accounting",
"Auditing",
"Tax Accounting",
"Forensic Accounting",
],
},
{
title: "Finance",
items: [
"Investment Management",
"Financial Risk Management",
"Corporate Finance",
"Public Finance",
"Personal Finance",
],
},
{
title: "Human Resources",
items: [
"Learning & Development",
"Performance Management",
"HR Information Systems",
"Compensation & Benefits",
"Recruiting & Staffing",
"Organizational Structure",
"Employee & Labor Relations",
"Diversity Equity & Inclusion",
],
},
{
title: "Information Technology",
items: [
"Systems Security",
"Data Management",
"IT Management",
"Network Administration",
"Software Development",
"Web Development",
],
},
{
title: "Legal",
items: [
"Litigation",
"Risk Management",
"Contract Law",
"Import/Export Law",
"Compliance Policies & Procedures",
"Property Law",
"Intellectual Property Law",
"Employment Law",
"Ethics",
"Law Enforcement",
"Criminal Justice",
],
},
{
title: "Manufacturing",
items: [
"Plant Management",
"Fabrication & Machining",
"Reliability & Asset Management",
"Procurement",
"Distribution",
"Production Installation",
],
},
{
title: "Operations",
items: [
"Improve Processes",
"LEAN & Six Sigma",
"Production Planning & Control",
"Quality Management",
"Supply Chain Management",
"Design Process",
],
},
{
title: "Marketing & Communication",
items: [
"Sales Support",
"Marketing Communications",
"Advertising Strategy",
"Pricing Strategy",
"Market Research",
"Social Media Strategy",
"Brand Management",
"Copy & Content Creation",
"Imaging/Graphics",
],
},
{
title: "Sales",
items: [
"Capture Management",
"Building a Book of Business",
"Channel Strategy",
"Sales Forecasting",
"Enterprise Sales",
"Inside Sales",
"Objection Handling",
"Business Development",
],
},
{
title: "Management",
items: [
"Delegation",
"Emotional Intelligence",
"Improve Processes",
"Product Management",
"Project Management",
"Decision Making",
"Negotiation Skills",
"Develop Others",
"Change Management",
"Priority Management",
"Effective Communication",
"Conflict Management",
],
},
{
title: "Leadership",
items: [
"Team Building",
"Shaping Culture",
"Setting Vision & Strategy",
"Strategic Thinking",
"Product Development",
"Service Development",
"Value Creation",
],
},
{
title: "Healthcare",
items: [
"Dentistry",
"Health Sciences",
"Physician",
"Veterinarian",
"Pharmacist",
"Healthcare Management",
"Patient Care",
],
},
{
title: "Education",
items: [
"Teaching",
"Education Administration",
"School Counseling",
"Curriculum Development",
],
},
{
title: "Consulting",
items: [
"Management Consulting",
"Corporate Consulting",
"Independent Consulting",
],
},
{
title: "Government & Public Administration",
items: [
"Revenue & Taxation",
"Law Enforcement",
"Public Management & Administration",
"Environmental & Resource Planning",
"National Security",
"Governance",
],
},
{
title: "Customer Service",
items: [
"Customer Retention",
"Customer Management",
"Customer Support",
"SaaS Customer Experience",
],
},
{
title: "Engineering",
items: [
"Civil Engineering",
"Chemical Engineering",
"Mechanical Engineering",
"Electrical Engineering",
"Industrial Engineering",
"Aerospace Engineering",
"Biomedical Engineering",
"Environmental Engineering",
"Computer Engineering",
"Materials/Textiles Engineering",
"Nuclear Engineering",
"Architecture",
],
},
{
title: "Sciences",
items: [
"Agricultural Science",
"Social Science",
"Biology",
"Chemistry",
"Political Science",
"Physics",
"Psychology",
"Mining & Petroleum",
],
},
{
title: "Social Services",
items: [
"Therapists",
"Probation Officer",
"Rehabilitation Counselor",
"Career Counselor",
"Social Worker",
"Substance Abuse Counselor",
"Mental Health Counselor",
"Clergy",
],
},
{
title: "Creative / Design",
items: [
"Creative Arts",
"Graphic Design",
"Interior Design",
"Product Design",
"User Experience",
],
},
];
const [initialInterestData, setInitialInterestData] = useState([]);
// Search Logic
// TODO: Later Search Logic
// Handle Next
const handleNext = async () => {
try {
// Construct the data object to send
const dataToSend = initialInterestData.map((interest) => ({
title: interest.title,
selectedItems: interest.items
.filter((item, index) => selectedItems[index])
.map((item, index) => ({
name: item,
rating: ratings[index],
})),
}));
console.log(dataToSend);
// Make the HTTP request to the backend API
const response = await axios.post(
"http://172.20.10.3:8080/onboarding/v3",
dataToSend
);
// Handle response as needed (e.g., show success message, navigate to next screen)
console.log("Response from backend:", response.data);
navigation.navigate("Career"); // Navigate to the next screen
} catch (error) {
// Handle error (e.g., show error message)
console.error("Error sending data to backend:", error);
}
};
return (
// Margin Top is missing in this. i want same level of margin as my previous pages.
<SafeAreaView style={{ flex: 1, alignItems: "center", marginTop: 40 }}>
<TouchableOpacity
onPress={() => {
navigation.goBack();
}}
style={{
position: "absolute",
top: 3,
left: 20,
justifyContent: "center",
alignItems: "center",
flexDirection: "row",
}}
>
<Icon name="chevron-left" size={24} color="#000" />
</TouchableOpacity>
<Text style={{ fontWeight: "bold", fontSize: 20, marginBottom: 5 }}>
Areas of Interest
</Text>
<View style={{ width: 400, height: 1.5, backgroundColor: "#DBD4D4" }} />
<FlatList
data={interestData}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item }) => <InterestList data={item} />}
ListHeaderComponent={() => (
<>
<Text
style={{ fontSize: 17, marginTop: 10, paddingHorizontal: 15 }}
>
Select areas of interest and rate your expertise in each to
receive personalized mentoring recommendations. Rate your
expertise with the star system (1 - 5) to establish your
proficiency.
</Text>
<Text
style={{
fontSize: 11,
color: "#9C9C9C",
textAlign: "left",
marginTop: 10,
paddingHorizontal: 15,
}}
>
Your ratings are confidential and not displayed on your profile.
We recommend selecting at least 3 options.
</Text>
<View
style={{
flexDirection: "row",
alignItems: "center",
backgroundColor: "#F1F1F3",
width: "90%",
height: 50,
borderRadius: 20,
marginTop: 15,
paddingHorizontal: 20,
borderColor: "#D9D9D9",
borderWidth: 1,
marginHorizontal: 15,
}}
>
<Icon name="search" size={15} color="#9C9C9C" />
<TextInput
placeholder="Search Here"
style={{ flex: 1, marginLeft: 10 }}
/>
</View>
</>
)}
/>
<View style={{ flexDirection: "row", height: 10, marginVertical: 10 }}>
<NavigationLine active={true} />
<NavigationLine active={true} />
<NavigationLine active={true} />
<NavigationLine active={false} />
<NavigationLine active={false} />
</View>
<TouchableOpacity
onPress={handleNext}
style={{
backgroundColor: "#09A1F6",
padding: 10,
borderRadius: 30,
width: "90%",
height: 50,
justifyContent: "center",
alignItems: "center",
marginBottom: 10,
}}
>
<Text style={{ color: "#fff", fontSize: 24, fontWeight: "bold" }}>
Next
</Text>
</TouchableOpacity>
</SafeAreaView>
);
};
export default AreasOfInterest;