1

I have a problem with my code. I have a tag with options, when I try to set contact type set contact type appears white screen with error in the console "types.map() is not a function" white screen with errors. I think the problem comes from that at the beginning "types" are array and when I choose contact type with the state() "types" become a single value. I don't know how to fix that.

This is my code:

import React, { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import styles from './postContact.module.css';

const PostContact = () => {
const [nickName, setNickName] = useState('');
const [address, setAddress] = useState('');
const [phoneNumber, setPhoneNumber] = useState('');
const [account, setAccount] = useState('');
const [types, setType] = useState([]);
const navigate = useNavigate();

const postContact = async (e) => {
    e.preventDefault();

    await fetch('http://localhost:5090/api/contacts', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            nickName,
            address,
            phoneNumber,
            userId: 1,
            contactTypeId: types,
            account
        })
    })
        .then(() => {
            navigate('/');
        })
        .catch((e) => {
            alert(e.message)
        });
};

const getTypes = async () => {
    const request = await fetch('http://localhost:5090/api/contactTypes', {
        method: 'GET',
        headers: {
            'Content-Type': 'application/json'
        }
    });

    const response = await request.json();
    setType(response);
};

useEffect(() => {
    getTypes();
}, []);

return (
    <form className={styles['post-form']} onSubmit={postContact}>
        <label htmlFor='nickName'>Nickname</label>
        <input className={styles.input} id='nickName' type='text' onChange={e => setNickName(e.target.value)} value={nickName} />
        <label htmlFor='address'>Address</label>
        <textarea className={styles.input} id='address' type='text' onChange={e => setAddress(e.target.value)} value={address} />
        <label htmlFor='phoneNumber'>Phone Number</label>
        <input className={styles.input} id='phoneNumber' type='text' onChange={e => setPhoneNumber(e.target.value)} value={phoneNumber} />
        <label htmlFor='account'>Account</label>
        <input className={styles.input} id='account' type='text' onChange={e => setAccount(e.target.value)} value={account} />
        <label htmlFor="type">Contact Type</label>
        <select className={styles.input} title="type" name="type" onChange={e => setType(e.target.value)} value={types}>
            {types.map(type=>
                <option key={type.id} value={type.id}>{type.type}</option> 
            )}
        </select>
        <button className="btn btn-primary mt-5" type='submit' name='Post'>Create</button>
    </form>
);
};

export default PostContact;

I'll be grateful if anyone can help me.

1
  • make sure types is not null Commented Mar 14, 2022 at 13:36

2 Answers 2

3

On the first render the value for types will be undefined ( on sync code execution ), try using it as

<select className={styles.input} title="type" name="type" onChange={e => setType(e.target.value)} value={types}>
            {types?.map(type=>
                <option key={type.id} value={type.id}>{type.type}</option> 
            )}
        </select>

? will make sure to run map once value for types is there ( also make sure it is mappable ( is an array ))

Sign up to request clarification or add additional context in comments.

3 Comments

Also, if the JSON response is not an array, you'll have to convert it to an array first.
Didn't work for me.
the answer is specific to the given code, there can be other reasons too. Please make a new Question for this one with sample code, or share code here. thanks
0

Handle the array falsy cases before doing any operations on it

<select 
  className={styles.input} 
  title="type" name="type" 
  onChange={e => setType(e.target.value)} 
  value={types}
>
    {types.length && types.map(type=>
        <option key={type.id} value={type.id}>{type.type}</option> 
     )}
</select>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.