1

Good afternoon everyone. I have 2 pages: one responsible for displaying List of Users in the table (data comes from fetching), then on Add User button click opens a Modal window with Sign Up form. On submitting this form, data about a new user is sent to an api (fetch POST), then sign up form closes and then the List of Users table is supposed to be updated with a newly added user. I fail to figure out how to correctly perform this update. Simple getUser() call in handleUserFormSubmit function doesn't do the trick (table is not re-rendered). Thanks in advance for any help

// Sign-Up Form Component

import React, { useState, useEffect } from "react";

const SignUpForm = ({
  isFormVisible,
  setIsFormVisible,
  userList,
  getUsers,
}) => {
  const [usernameList, setUsernameList] = useState([]);
  const [username, setUsername] = useState("");
  const [usertype, setUsertype] = useState("");
  const [password, setPassword] = useState("");
  const [verifyPassword, setVerifyPassword] = useState("");
  const [isChecked, setIsChecked] = useState(true);
 

  const getUsernameList = () =>
    userList.forEach(({ username }) => usernameList.push(username));
  
  useEffect(() => {
    getUsernameList();
    console.log(usernameList);
  }, []);

  const addNewUser = async () => {
    try {
      const response = await fetch(
        "http://www.someapi.com/add",
        {
          method: "POST",
          headers: {
            Accept: "application/json",
            "Content-Type": "application/json",
          },
          body: JSON.stringify({
            username,
            usertype,
            password,
          }),
        }
      );
      const data = await response.json();
      console.log(data);
    } catch (error) {
      console.error(error.message);
    }
  };


  const handleUserFormSubmit = (e) => {
    e.preventDefault();
      addNewUser();
      setIsFormVisible(false);
      getUsers();
    }
  };

  return (
    <>
      {isFormVisible && (
        <div
          className={`${
            isFormVisible ? "modal-overlay show-modal" : "modal-overlay"
          }`}
        >
          <div className="sign-up-container">
            <div className="sign-up-header-container">
              <h2>Sign Up</h2>
              <p>Please fill in this form to create an acoount</p>
            </div>
            <form className="form" onSubmit={(e) => e.preventDefault()}>
              <label htmlFor="username">Username</label>{" "}
              <br />
              <input
                type="text"
                placeholder="Enter username"
                id="username"
                name="username"
                value={username}
                required
                onChange={(e) => {
                  setUsername(e.target.value.toLowerCase());
                  setIsNameProvided(true);
                }}
              />
              <br />
              <label htmlFor="usertype">User type</label>{" "}
              <br />
              <select
                name="usertype"
                id="usertype-select"
                required
                onChange={(e) => {
                  setUsertype(e.target.value);
                  setIsTypeSelected(true);
                }}
              >
                <option value=""></option>
                <option value="instructor">instructor</option>
                <option value="maintenance">maintenance</option>
              </select>
              <br />
              <label htmlFor="password">Password</label>{" "}
              <br />
              <input
                type="password"
                placeholder="Enter password"
                id="password"
                name="password"
                required
                value={password}
                onCopy={(e) => e.preventDefault()}
                onPaste={(e) => e.preventDefault()}
                onChange={(e) => {
                  setPassword(e.target.value);
                  setIsPasswordProvided(true);
                }}
              />
              <br />
              <label htmlFor="rpassword">Repeat Password</label>{" "}
              
              <br />
              <input
                type="password"
                placeholder="Repeat"
                id="rpassword"
                name="rpassword"
                required
                value={verifyPassword}
                onCopy={(e) => e.preventDefault()}
                onPaste={(e) => e.preventDefault()}
                onChange={(e) => {
                  setVerifyPassword(e.target.value);
                  setIsConfirmPasswordProvided(true);
                }}
            
              />{" "}
              <br />
              <input
                type="checkbox"
                id="remember"
                name="remember"
                checked={isChecked}
                onChange={() => setIsChecked(!isChecked)}
              />
              <label htmlFor="remember">Remember me</label>
              <p className="terms-privacy">
                By creating an account you agree to our{" "}
                <a href="#">Terms & Privacy</a>
              </p>
              <div className="btn-container">
                <button
                  type="button"
                  className="cancel-btn"
                  onClick={() => setIsFormVisible(false)}
                >
                  CANCEL
                </button>
                <button
                  type="submit"
                  className="sign-up-btn"
                  onClick={(e) => handleUserFormSubmit(e)}
                >
                  SIGN UP
                </button>
              </div>
            </form>
          </div>
        </div>
      )}
    </>
  );
};

export default SignUpForm;
// List Of Users Component:

import React, { useState, useEffect } from "react";

import Loading from "./Loading";
import SignUpForm from "./SignUpForm";
import "./User.css";

const User = () => {
  const [userList, setUserList] = useState([]);
  const [loading, setLoading] = useState(true);
  const [isFormVisible, setIsFormVisible] = useState(false);

  const getUsers = async () => {
    setLoading(true);
    try {
      const response = await fetch(
        "http://www.someapi.com"
      );
      const data = await response.json();
      setUserList(data);
      setLoading(false);
    } catch (error) {
      console.error(error.message);
      setLoading(false);
    }
  };

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


  if (loading) return <Loading />;

  return (
    <section className="section-user">
      <h1>List of Users</h1>
      <div className="users-table-container">
        <table className="users-table">
          <thead>
            <tr>
              <th>Username</th>
              <th>User type</th>
            </tr>
          </thead>
          <tbody>
            {userList.map(({ username, userType, hashedPswd }) => (
              <tr key={hashedPswd}>
                <td>{username}</td>
                <td>{userType}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
      <button className="add-user-btn" onClick={() => setIsFormVisible(true)}>
        Add User
      </button>
      {isFormVisible && (
        <SignUpForm
          isFormVisible={isFormVisible}
          setIsFormVisible={setIsFormVisible}
          userList={userList}
          getUsers={getUsers}
        />
      )}
    </section>
  );
};

export default User;

2 Answers 2

1

You are directly manipulating a state rather than using setState. In this case react does not re-render the page even if you manipulate the state. So:

// wrong
const getUsernameList = () =>
   userList.forEach(({ username }) => usernameList.push(username));
// correct
const getUsernameList = () => { 
    const list = userList.map(user => user.username)
    setUsernameList(list)
}

*Edit: I think you are not saving your response data after creating a new user

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

4 Comments

didn't solve the problem, unfortunately
as for not saving response data - the problem is that I don't get the updated list of users as the response, I just get a message about adding a new user
If you could not solve the problem yet, I can collaborate. Let me know
hey, I asked my colleague to send me back the added user instead of a string, updated the state with it and now it's working. thanks for your help
0

In User component add

useEffect(() => {
 if (isFormVisible) getUsers();

}, [isFormVisible]);

1 Comment

didn't work, unfortunately

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.