简体   繁体   中英

How to handle request and avoid code duplication?

What I want to do is to avoid code duplication managing the response from the request that has been made and serving the output to the components throughout the useState.

In this case, as soon as the page is loaded useEffect is triggered. It makes the request and handles the response using setLoadedPlaces to set the data to searchedPlace and setMarker to set the data to markersMap.

If the user makes a new request, data is treated in the same way as with the useEffect function, the only difference is that the request is made with POST with a body attached.

I thought that make only one request would be sufficient but how?

Here there is a lot going on in both functions, I tried to extrapolate the result but returned a promise, which has to be handle with .then(() => {}) because is asynchronous, but how?

  const [searchedPlaces, setLoadedPlaces] = useState();
  const [MarkersMap, setMarkersMap] = useState();

useEffect()

    useEffect(() => {
        const fetchPlaces = async () => {
          try {
            const responseData = await sendRequest(
              "http://localhost:5000/api/search"
            );

            //here I assign the data to setsetLoadedPlaces

            setLoadedPlaces(responseData.elements);

            //here I extrapolate lng and lat and assign to setMarkersMap

            let locations = [];
            responseData.elements.map(element => {
            element.location.lat = parseFloat(element.location.lat);
            element.location.lng = parseFloat(element.location.lng);
              locations.push(element.location);
              return locations;
            });
            setMarkersMap(locations);
          } catch (err) {}
        };
        fetchPlaces();
      }, [sendRequest]);

receivedInputs() which is triggered by a button

const receivedInputs = async val => {
    console.log(val.address);
    try {
        let responseData = await fetch("http://localhost:5000/api/search?", {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            body: JSON.stringify({
                address: val.address.value.toLowerCase(),
                price: val.price.value.toLowerCase(),
                leaseTime: val.leaseTime.value.toLowerCase()
            })
        });

        let fetchPlaces = await responseData.json();

        //here I assign the data to setsetLoadedPlaces

        setLoadedPlaces(fetchPlaces.elements);

        //here I extrapolate lng and lat and assign to setMarkersMap

        let locations = [];
        fetchPlaces.elements.map(element => {
            element.location.lat = parseFloat(element.location.lat);
            element.location.lng = parseFloat(element.location.lng);
            locations.push(element.location);
            return locations;
        });

        setMarkersMap(locations);

    } catch (err) {
        console.log(err);
    }
};

It looks like you should just lift out this part into its own function:

const handleResponseData = responseData => {
    setLoadedPlaces(responseData.elements);
    const locations = responseData.elements.map(element => {
          element.location.lat = parseFloat(element.location.lat);
          element.location.lng = parseFloat(element.location.lng);
          return element;
    });
   setMarkersMap(locations);
}  

Then just call it:

 useEffect(() => {
    const fetchPlaces = async () => {
      try {
        const responseData = await sendRequest(
          "http://localhost:5000/api/search"
        );

       handleResponseData(responseData)
      } catch (err) {}
    };
    fetchPlaces();
  }, [sendRequest]);


const SearchSubmitHandler = async event => {
    event.preventDefault();
    try {
      let responseData = await fetch("http://localhost:5000/api/search?", {
        method: "POST",
        headers: {
          "Content-Type": "application/json"
        },
        body: JSON.stringify({
          address: formState.inputs.address.value.toLowerCase(),
          price: formState.inputs.price.value.toLowerCase(),
          leaseTime: formState.inputs.leaseTime.value.toLowerCase()
        })
      });

      handleResponseData(responseData.json())

    } catch (err) {
      console.log(err);
    }
  };

create a function that fetch and call that function in your useEffect hook and in your callback.

const Component = () => {

const fetch = aynsc () => { //... }

useEffect(() => { fetch() }, [])

searchSubmitHandler = () => { fetch() }

return {}

}

Ok, I managed the solution in this way, I considered Will Jenkins answer and added a then() method because it is returning a Promise. Which carries "response" as an argument if the request success.

  //                              ***      useEffect      ***

useEffect(() => {
    const fetchPlaces = async () => {
      try {
        const responseData = await sendRequest(
          "http://localhost:5000/api/search"
        );

        return responseData;
      } catch (err) {}
    };
    fetchPlaces().then(response => {
      handleResponseData(response);
    });
  }, [sendRequest]);

  //                              ***      Request      ***

  const receivedInputs = async val => {
    try {
      let responseData = await fetch("http://localhost:5000/api/search?", {
        method: "POST",
        headers: {
          "Content-Type": "application/json"
        },
        body: JSON.stringify({
          address: val.address.value.toLowerCase(),
          price: val.price.value.toLowerCase(),
          leaseTime: val.leaseTime.value.toLowerCase()
        })
      });
      return responseData.json().then(response => {
        handleResponseData(response);
      });
    } catch (err) {
      console.log(err);
    }
  };

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM