-3

hello i am not sure why i getting this error massage can some one correct my code i can not find key in my new post components

this is my newpost.js code

import React, { useContext } from 'react';
import { useHttpClient } from '../../hooks/useHttpClient';
import useForm from '../../hooks/useForm';
import { AuthContext } from '../../context/auth';
import { useHistory } from 'react-router-dom/cjs/react-router-dom.min';
import { newPostForm } from '../../utils/formConfig';
import { appendData, renderRepeatedSkeletons } from '../../utils';
import ErrorModal from '../../components/Modal/ErrorModal';
import SkeletonElement from '../../components/Skeleton/SkeletonElement';

const NewPost = () => {
  const auth = useContext(AuthContext);
  const history = useHistory();
  const { currentUser } = auth;
  const { isLoading, sendReq, error, clearError } = useHttpClient();
  const { renderFormInputs, renderFormValues, isFormValid } =
    useForm(newPostForm);
  const formValues = renderFormValues();
  const formInputs = renderFormInputs();

  const postSubmitHandle = async (evt) => {
    evt.preventDefault(); //otherwise, there will be a reload
    const formData = appendData(formValues);
    formData.append('author', currentUser.userId);
    try {
      await sendReq(
        `${process.env.REACT_APP_BASE_URL}/posts`,
        'POST',
        formData,
        {
          Authorization: `Bearer ${currentUser.token}`,
        }
      );
      history.push('/');
    } catch (err) {}
  };

  return (
    <>
      <ErrorModal error={error} onClose={clearError} />
      {isLoading ? (
        renderRepeatedSkeletons(<SkeletonElement type='text' />, 20)
      ) : (
        <div className='container-create-page'>
          <form className='form form__create'>
            <h2>Create a new post</h2>
            {formInputs}
            <button
              onClick={postSubmitHandle}
              className='btn'
              disabled={!isFormValid()}
            >
              Submit <span>&rarr;</span>
            </button>
          </form>
        </div>
      )}
    </>
  );
};

export default NewPost;

and this is my useform.js code

import { useState, useCallback } from 'react';

//"signupForm" => "formObj" (name, email, password) => "form"
const useForm = (formObj) => {
  const [form, setForm] = useState(formObj);

  const renderFormInputs = () => {
    //renders an [] of <Input> for all input fields
    return Object.values(form).map((inputObj) => {
      const { value, label, errorMessage, valid, renderInput } = inputObj;
      return renderInput(
        onInputChange,
        value,
        valid,
        errorMessage,
        label,
        onCustomInputChange
      );
    });
  };

  const renderFormValues = () => {
    let values = {};
    Object.keys(form).forEach((inputObj) => {
      values[inputObj] = form[inputObj].value;
    });
    return values;
  };

  const isInputFieldValid = useCallback(
    (inputField) => {
      for (const rule of inputField.validationRules) {
        if (!rule.validate(inputField.value, form)) {
          inputField.errorMessage = rule.message;
          return false;
        }
      }
      return true;
    },
    [form]
  );

  const onInputChange = useCallback(
    (event) => {
      const { name, value } = event.target;
      let inputObj = { ...form[name], value };
      const isValidInput = isInputFieldValid(inputObj);
      if (isValidInput && !inputObj.valid) {
        inputObj = { ...inputObj, valid: true };
      } else if (!inputObj.touched && !isValidInput && inputObj.valid) {
        inputObj = { ...inputObj, valid: false };
      }
      inputObj = { ...inputObj, touched: true };
      setForm({ ...form, [name]: inputObj });
    },
    [form, isInputFieldValid]
  );

  const onCustomInputChange = useCallback(
    (type, value, InputIsValid) => {
      setForm({
        ...form,
        [type]: { ...form[type], value, valid: InputIsValid },
      });
    },
    [form]
  );

  const isFormValid = useCallback(
    (customForm) => {
      let isValid = true;
      const arr = Object.values(customForm || form);
      for (let i = 0; i < arr.length; i++) {
        if (!arr[i].valid) {
          isValid = false;
          break;
        }
      }
      return isValid;
    },
    [form]
  );

  return {
    renderFormInputs,
    renderFormValues,
    isFormValid,
    setForm,
  };
};

export default useForm;

submit button does not work . it just a simple form with submit button and 4 input value and one image . if some one need more information . please ask in the comment section

index.js contain renderRepeatedSkeletons

export const checkInArray = (arr, elem) => {
  return arr && arr.indexOf(elem) !== -1;
};

export const canModifyComment = (currentUserId, authorId) =>
  currentUserId === authorId;
export const canReply = (currentUserId) => !!currentUserId;
export const isReplying = (activeComment, commentId) =>
  activeComment &&
  activeComment.type === 'replying' &&
  activeComment.id === commentId;

export const isEditing = (activeComment, commentId) =>
  activeComment &&
  activeComment.type === 'editing' &&
  activeComment.id === commentId;

export const readingTime = (body) => {
  const wpm = 225;
  const words = body.trim().split(/\s+/).length;
  return `${Math.ceil(words / wpm)} min read`;
};

export const appendData = (data) => {
  const formData = new FormData();
  for (let [key, value] of Object.entries(data)) {
    if (Array.isArray(value)) {
      value = JSON.stringify(value);
    }
    formData.append(`${key}`, value);
  }
  return formData;
};

export const getReplies = (comments, commentId) => {
  return (
    comments &&
    comments
      .filter((comment) => comment && comment.parentId === commentId)
      .sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime())
  );
};

export const formatDate = (date) => {
  const options = { year: 'numeric', month: 'short', day: 'numeric' };
  const today = new Date(date);

  return today.toLocaleDateString('en-US', options);
};

export const getRandomColor = () => {
  const letters = '0123456789ABCDEF';
  let color = '#';
  for (let i = 0; i < 6; i++) {
    color += letters[Math.floor(Math.random() * 16)];
  }
  return color;
};

export const renderRepeatedSkeletons = (element, count) => {
  let skeletons = [];
  for (let i = 0; i < count; i++) {
    skeletons.push(element);
  }
  return skeletons;
};

export const renderAlternateSkeletons = (elementOne, elementTwo, count) => {
  let skeletons = [];
  for (let i = 0; i < count; i++) {
    if (i % 2 === 0) {
      skeletons.push(elementOne);
    } else {
      skeletons.push(elementTwo);
    }
  }
  return skeletons;
};
samurai
  • 47
  • 6
  • Show `renderRepeatedSkeletons` – Konrad Dec 10 '22 at 13:20
  • Does this answer your question? [Understanding unique keys for array children in React.js](https://stackoverflow.com/questions/28329382/understanding-unique-keys-for-array-children-in-react-js) – Emma Dec 10 '22 at 13:21
  • no no i check all the links from google in my search query . i could not fix – samurai Dec 10 '22 at 13:50
  • @konrad . thanks for answering but there is no renderRepeatSkeltons file ins source code . the source is here . https://github.com/eknoorpreet/dev.to-clone i was trying to learn line by line and learn project locally but there is no such file like this . – samurai Dec 10 '22 at 13:59
  • @konrad I found a file has the export RepeatedSkeltons . – samurai Dec 10 '22 at 14:05

1 Answers1

0

Your renderRepeatedSkeletons function have to add a key to elements

export const renderRepeatedSkeletons = (element, count) => {
  let skeletons = [];
  for (let i = 0; i < count; i++) {
    skeletons.push(<React.Fragment key={i} />{element}</React.Fragment>);
  }
  return skeletons;
};
Konrad
  • 21,590
  • 4
  • 28
  • 64