реагируйте, как не быть таким повторяющимся, используя крючки useState

#javascript #reactjs #react-hooks

Вопрос:

Я создаю форму, в которой используется множество полей для размещения данных в базе данных. У меня более 80 полей, таких как «заголовок, HTML-код тела, цена, сравнение цен, поставщик, вес» и т. Д. И мой код очень повторяющийся, есть ли способ сделать мой код короче? Я сбрил большую часть своего кода, потому что в нем более 600 строк кода, и было бы слишком сложно опубликовать все целиком, я сделал 2 отдельные функции handleChange и selectHandler в качестве небольших помощников, чтобы получить значение раскрывающихся datalist входных данных, в которые нужно хранить state … значения должны храниться в отдельных состояниях, так как мне нужно, чтобы каждое из них выполняло вызов axios для хранения своих определенных полей в нужном поле данных.

 import React, { useState } from "react";

function handleChange(e, setter) {
  return setter({ value: e.target.value });
}

function selectHandler(setter) {
  return (
    <>
      <input
        list="headers"
        placeholder="Select one"
        onChange={(e) => handleChange(e, setter)}
      />
      {/* headers comes from mapped api in another file */}
      <datalist id="headers">{headers}</datalist>
    </>
  );
}

function PushToDB() {
  const [showExtraImageInputs, setShowExtraImageInputs] = useState(false);

  const [titleHeader, setTitleHeader] = useState();
  const [handleHeader, setHandleHeader] = useState();
  const [descriptionHtmlHeader, setDescriptionHtmlHeader] = useState();
  const [image1Header, setImage1Header] = useState();
  const [image2Header, setImage2Header] = useState();
  const [altText1, setAltText1] = useState();
  const [altText2, setAltText2] = useState();

  return (
    <>
      <form onSubmit={(e) => e.preventDefault()}>
        // each label uses the helpers to get the dropdown values and store it in state
        <label>Title: {selectHandler(setTitleHeader)}</label>
        <label>Body html: {selectHandler(setDescriptionHtmlHeader)}</label>
        <label>Handle: {selectHandler(setHandleHeader)}</label>
        <label>Image: {selectHandler(setImage1Header)}</label>
        <label>Img alt text: {selectHandler(setAltText1)}</label>
        {/* ADD MORE IMAGES */}
        {showExtraImageInputs amp;amp; (
          <>
            <div>Image 2: {selectHandler(setImage2Header)}</div>
            <div>Img alt text 2: {selectHandler(setAltText2)}</div>
          </>
        )}
      </form>
    </>
  );
}
export default PushToDB;
 

вот как выглядят данные axios. как вы можете видеть, мне нужно каждое значение из штата. и опять же, это более 80 полей.

 useEffect(() => {
  if (pushState amp;amp; apiData) {
    let productValues = apiData.data.data;
    productValues.map((e) => {
      let url = `url`;
      return axios
        .get(url)
        .then((res) => {
          if (res) {
            // if the data is already in db, do not push
            if (res.data.products.length === 0)
            // if there is no data then push data
              return setProductData({
                variables: {
                  // values from state
                  title: e[titleHeader?.value],
                  descriptionHtml: e[descriptionHtmlHeader?.value],
                  handle: e[handleHeader?.value],
                  img1: e[image1Header?.value] ?? "",
                  alt1: e[altText1?.value],
                  img2 : e[image2Header?.value] ?? '',
                  alt2: e[altText2?.value], 
                  img3: e[image3Header?.value] ?? '',
                  // and so on
                },
              });
          }
          // this is the logger of whats being pushed into the database
        })
        .then((res) => {
          if (res)
            return axios.post("http://localhost:4000/api/v1/Extradb", {
              data: {
                title: res?.data?.productCreate?.product?.title,
                handle: res?.data?.productCreate?.product?.handle,
                item_id: res?.data?.productCreate?.product?.id,
              },
            });
        });
    });
  }
}, []);
 

Ответ №1:

пришло решение… Мне просто нужно было сделать объект

 function App() {
  const [userInputs, setUserInputs] = useState({})

  function handleChange(e) {
    const { value, name } = e.target
    setUserInputs(prevState => ({
      ...prevState,
      [name]: value
    }))
  }

  function handleInputNaming(name) {
    let capitilizedWord = name.charAt(0).toUpperCase()   name.slice(1);
    return (<input placeholder={capitilizedWord} name={name} value={userInputs[name]} onChange={handleChange} />)
  }

  return (
    <div className="App">
      {handleInputNaming('title')}
      {handleInputNaming('handle')}
      {handleInputNaming('image')}
    </div>
  );
}

export default App;