score:3

Accepted answer

you need to do something in the following place:

  const addname = (event) => {
    event.preventdefault();
    const nameobject = {
      name: newname
    };
    setpersons([...persons, nameobject]);
  };

use .find() on the persons array to find the particular name already existing and add the condition before setpersons is executed.

if (persons.find(p => p.name === newname)) {
  window.alert("name already exists!");
  return false;
}

a code like above will work.

import react, { usestate } from "react";

const app = () => {
  const [persons, setpersons] = usestate([{ name: "arto hellas" }]);
  const [newname, setnewname] = usestate("");

  const addname = (event) => {
    event.preventdefault();
    if (persons.find((p) => p.name === newname)) {
      window.alert("name already exists!");
      return false;
    }
    const nameobject = {
      name: newname
    };
    setpersons([...persons, nameobject]);
  };

  const handlenamechange = (event) => {
    setnewname(event.target.value);
  };

  return (
    <div>
      <h2>phonebook</h2>
      <form onsubmit={addname}>
        <div>
          name: <input value={newname} onchange={handlenamechange} />
        </div>
        <div>
          <button type="submit">add</button>
        </div>
      </form>
      <h2>numbers</h2>
      {persons.map((person) => (
        <p key={person.name}>{person.name}</p>
      ))}
    </div>
  );
};

export default app;

demo: https://codesandbox.io/s/nervous-poitras-i3stw?file=/src/app.js:0-958

the above code shows an ugly error alert using the normal window alert. if you want a better error like this:

preview

you can use the following code, by setting a state:

import react, { usestate } from "react";
import "./styles.css";

const app = () => {
  const [persons, setpersons] = usestate([{ name: "arto hellas" }]);
  const [newname, setnewname] = usestate("");
  const [error, seterror] = usestate(false);

  const addname = (event) => {
    event.preventdefault();
    if (persons.find((p) => p.name === newname)) {
      seterror(true);
      return false;
    }
    const nameobject = {
      name: newname
    };
    setpersons([...persons, nameobject]);
  };

  const handlenamechange = (event) => {
    setnewname(event.target.value);
  };

  return (
    <div>
      <h2>phonebook</h2>
      <form onsubmit={addname}>
        {error && <p classname="error">user already exists.</p>}
        <div>
          name: <input value={newname} onchange={handlenamechange} />
        </div>
        <div>
          <button type="submit">add</button>
        </div>
      </form>
      <h2>numbers</h2>
      {persons.map((person) => (
        <p key={person.name}>{person.name}</p>
      ))}
    </div>
  );
};

export default app;

and here's our style.css:

.error {
  background-color: red;
  color: #fff;
  padding: 5px;
}

demo: https://codesandbox.io/s/vibrant-tree-wsou2?file=/src/app.js

score:0

you can use the find method to search for a person with the newname. please check the below code-snippet:

const addname = (event) => {
    event.preventdefault()
    const nameobject = {
        name: newname,
    }
    let personalreadyexists = persons.find(person => person.name === newname);

    if (personalreadyexists) {
        alert('person with that name already exists');
        // any other operations (like clearing user input in the form, etc..)
    }
    else {
        setpersons([...persons, nameobject])
    }
}

code-sandbox

score:1

first add field to check name exists or not:

const nameexists = react.usememo(() => {
    return persons.some(item => item.name === newname);
  }, [newname, persons])

then disable button and show message if name exists:

<div>
          {nameexists && <p>name {newname} already exists!</p>}
          <button type="submit" disabled={nameexists} >add</button>
        </div>

also, make sure you clear name when you add new name:

const addname = (event) => { 
      ... 
      setnewname('')
  }

const app = () => {
  const [ persons, setpersons ] = react.usestate([  { name: 'arto hellas' }]) 
  const [ newname, setnewname ] = react.usestate('')

  const addname = (event) => {
      event.preventdefault()
      const nameobject = {
          name: newname,
      }
      setpersons([...persons,nameobject]);
      
      setnewname('')
  }

  const handlenamechange = (event) => {
      setnewname(event.target.value)
  }
  
  const nameexists = react.usememo(() => {
    return persons.some(item => item.name === newname);
  }, [newname, persons])
 

  return (
    <div>
      <h2>phonebook</h2>
      <form onsubmit={addname} >
        <div>
          name: <input value={newname} onchange={handlenamechange} />
        </div>
        <div>
          {nameexists && <p>name {newname} already exists!</p>}
          <button type="submit" disabled={nameexists} >add</button>
        </div>
      </form>
      <h2>numbers</h2>
        {persons.map(person => (
            <p key={person.name}>{person.name}</p>
        ))}
        
    </div>
  )
}

reactdom.render(<app />, document.getelementbyid('root'))
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<div id="root"></div>


Related Query

More Query from same tag