feat: reactive search with useEffect
This commit is contained in:
		
							parent
							
								
									23a4003f31
								
							
						
					
					
						commit
						c92d131ae3
					
				| 
						 | 
				
			
			@ -15,8 +15,8 @@ export const getServerSideProps: GetServerSideProps = async (context) => {
 | 
			
		|||
 | 
			
		||||
  let initialQueryParameters = {
 | 
			
		||||
    query: "",
 | 
			
		||||
    numDisplay: 21,
 | 
			
		||||
    starsThreshold: 2,
 | 
			
		||||
    numDisplay: 21, // 20
 | 
			
		||||
    forecastsThreshold: 0,
 | 
			
		||||
    forecastingPlatforms: platformsWithLabels, // weird key value format,
 | 
			
		||||
    ...urlQuery,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
import React, { Fragment, useState } from 'react';
 | 
			
		||||
import React, { Fragment, useEffect, useState } from 'react';
 | 
			
		||||
 | 
			
		||||
import { platformNames, PlatformWithLabel } from '../platforms';
 | 
			
		||||
import searchAccordingToQueryData from '../worker/searchAccordingToQueryData';
 | 
			
		||||
| 
						 | 
				
			
			@ -7,14 +7,17 @@ import Form from './form';
 | 
			
		|||
import MultiSelectPlatform from './multiSelectPlatforms';
 | 
			
		||||
import { SliderElement } from './slider';
 | 
			
		||||
 | 
			
		||||
export interface QueryParameters {
 | 
			
		||||
interface QueryParametersWithoutNum {
 | 
			
		||||
  query: string;
 | 
			
		||||
  numDisplay: number;
 | 
			
		||||
  starsThreshold: number;
 | 
			
		||||
  forecastsThreshold: number;
 | 
			
		||||
  forecastingPlatforms: PlatformWithLabel[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface QueryParameters extends QueryParametersWithoutNum {
 | 
			
		||||
  numDisplay: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface Props {
 | 
			
		||||
  initialResults: any;
 | 
			
		||||
  defaultResults: any;
 | 
			
		||||
| 
						 | 
				
			
			@ -64,17 +67,13 @@ const CommonDisplay: React.FC<Props> = ({
 | 
			
		|||
}) => {
 | 
			
		||||
  /* States */
 | 
			
		||||
 | 
			
		||||
  const [queryParameters, setQueryParameters] = useState(
 | 
			
		||||
    initialQueryParameters
 | 
			
		||||
  );
 | 
			
		||||
  let initialSearchSpeedSettings = {
 | 
			
		||||
    timeoutId: null,
 | 
			
		||||
    awaitEndTyping: 500,
 | 
			
		||||
    time: Date.now(),
 | 
			
		||||
  };
 | 
			
		||||
  const [searchSpeedSettings, setSearchSpeedSettings] = useState(
 | 
			
		||||
    initialSearchSpeedSettings
 | 
			
		||||
  const [queryParameters, setQueryParameters] =
 | 
			
		||||
    useState<QueryParametersWithoutNum>(initialQueryParameters);
 | 
			
		||||
 | 
			
		||||
  const [numDisplay, setNumDisplay] = useState(
 | 
			
		||||
    initialQueryParameters.numDisplay || 21
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  const [results, setResults] = useState(initialResults);
 | 
			
		||||
  const [advancedOptions, showAdvancedOptions] = useState(false);
 | 
			
		||||
  const [whichResultToDisplayAndCapture, setWhichResultToDisplayAndCapture] =
 | 
			
		||||
| 
						 | 
				
			
			@ -128,10 +127,9 @@ const CommonDisplay: React.FC<Props> = ({
 | 
			
		|||
    showIdToggle,
 | 
			
		||||
  }) => {
 | 
			
		||||
    let numDisplayRounded =
 | 
			
		||||
      queryParameters.numDisplay % 3 != 0
 | 
			
		||||
        ? queryParameters.numDisplay +
 | 
			
		||||
          (3 - (Math.round(queryParameters.numDisplay) % 3))
 | 
			
		||||
        : queryParameters.numDisplay;
 | 
			
		||||
      numDisplay % 3 != 0
 | 
			
		||||
        ? numDisplay + (3 - (Math.round(numDisplay) % 3))
 | 
			
		||||
        : numDisplay;
 | 
			
		||||
    return displayForecastsWrapper({
 | 
			
		||||
      results,
 | 
			
		||||
      numDisplay: numDisplayRounded,
 | 
			
		||||
| 
						 | 
				
			
			@ -140,19 +138,20 @@ const CommonDisplay: React.FC<Props> = ({
 | 
			
		|||
    });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  /* State controllers */
 | 
			
		||||
  let onChangeSearchInputs = (newQueryParameters: QueryParameters) => {
 | 
			
		||||
    setQueryParameters(newQueryParameters); // ({ ...newQueryParameters, processedUrlYet: true });
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    setResults([]);
 | 
			
		||||
    clearTimeout(searchSpeedSettings.timeoutId);
 | 
			
		||||
    let newtimeoutId = setTimeout(async () => {
 | 
			
		||||
      let urlSlug = transformObjectIntoUrlSlug(newQueryParameters);
 | 
			
		||||
    let newTimeoutId = setTimeout(async () => {
 | 
			
		||||
      let urlSlug = transformObjectIntoUrlSlug({
 | 
			
		||||
        ...queryParameters,
 | 
			
		||||
        numDisplay,
 | 
			
		||||
      });
 | 
			
		||||
      let urlWithoutDefaultParameters = urlSlug
 | 
			
		||||
        .replace("?query=&", "?")
 | 
			
		||||
        .replace("&starsThreshold=2", "")
 | 
			
		||||
        .replace("&numDisplay=21", "")
 | 
			
		||||
        .replace("&forecastsThreshold=0", "")
 | 
			
		||||
        .replace(`&forecastingPlatforms=${platformNames.join("|")}`, "");
 | 
			
		||||
      console.log(urlWithoutDefaultParameters);
 | 
			
		||||
      if (urlWithoutDefaultParameters != "?query=") {
 | 
			
		||||
        if (typeof window !== "undefined") {
 | 
			
		||||
          if (!window.location.href.includes(urlWithoutDefaultParameters)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -165,34 +164,40 @@ const CommonDisplay: React.FC<Props> = ({
 | 
			
		|||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      executeSearchOrAnswerWithDefaultResults(newQueryParameters);
 | 
			
		||||
      setSearchSpeedSettings({ ...searchSpeedSettings, timeoutId: null });
 | 
			
		||||
    }, searchSpeedSettings.awaitEndTyping);
 | 
			
		||||
    setSearchSpeedSettings({ ...searchSpeedSettings, timeoutId: newtimeoutId });
 | 
			
		||||
      executeSearchOrAnswerWithDefaultResults({
 | 
			
		||||
        ...queryParameters,
 | 
			
		||||
        numDisplay,
 | 
			
		||||
      });
 | 
			
		||||
    }, 500);
 | 
			
		||||
 | 
			
		||||
    // avoid sending results if user has not stopped typing.
 | 
			
		||||
  };
 | 
			
		||||
    return () => {
 | 
			
		||||
      clearTimeout(newTimeoutId);
 | 
			
		||||
    };
 | 
			
		||||
  }, [queryParameters]);
 | 
			
		||||
 | 
			
		||||
  /* State controllers */
 | 
			
		||||
 | 
			
		||||
  /* Change the stars threshold */
 | 
			
		||||
  let onChangeStars = (value: number) => {
 | 
			
		||||
    let newQueryParameters: QueryParameters = {
 | 
			
		||||
    setQueryParameters({
 | 
			
		||||
      ...queryParameters,
 | 
			
		||||
      starsThreshold: value,
 | 
			
		||||
    };
 | 
			
		||||
    onChangeSearchInputs(newQueryParameters);
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  /* Change the number of elements to display  */
 | 
			
		||||
  let displayFunctionNumDisplaySlider = (value) => {
 | 
			
		||||
    return Math.round(value) != 1
 | 
			
		||||
      ? "Show " + Math.round(value) + " results"
 | 
			
		||||
      : "Show " + Math.round(value) + " result";
 | 
			
		||||
    return (
 | 
			
		||||
      "Show " +
 | 
			
		||||
      Math.round(value) +
 | 
			
		||||
      " result" +
 | 
			
		||||
      (Math.round(value) === 1 ? "" : "s")
 | 
			
		||||
    );
 | 
			
		||||
  };
 | 
			
		||||
  let onChangeSliderForNumDisplay = (event) => {
 | 
			
		||||
    let newQueryParameters: QueryParameters = {
 | 
			
		||||
      ...queryParameters,
 | 
			
		||||
      numDisplay: Math.round(event[0]),
 | 
			
		||||
    };
 | 
			
		||||
    onChangeSearchInputs(newQueryParameters); // Slightly inefficient because it recomputes the search in time, but it makes my logic easier.
 | 
			
		||||
    setNumDisplay(Math.round(event[0]));
 | 
			
		||||
    // FIXME - force new search if numDisplay is greater than last search limit
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  /* Change the forecast threshold */
 | 
			
		||||
| 
						 | 
				
			
			@ -200,26 +205,26 @@ const CommonDisplay: React.FC<Props> = ({
 | 
			
		|||
    return "# Forecasts > " + Math.round(value);
 | 
			
		||||
  };
 | 
			
		||||
  let onChangeSliderForNumForecasts = (event) => {
 | 
			
		||||
    let newQueryParameters = {
 | 
			
		||||
    setQueryParameters({
 | 
			
		||||
      ...queryParameters,
 | 
			
		||||
      forecastsThreshold: Math.round(event[0]),
 | 
			
		||||
    };
 | 
			
		||||
    onChangeSearchInputs(newQueryParameters);
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  /* Change on the search bar */
 | 
			
		||||
  let onChangeSearchBar = (value: string) => {
 | 
			
		||||
    let newQueryParameters = { ...queryParameters, query: value };
 | 
			
		||||
    onChangeSearchInputs(newQueryParameters);
 | 
			
		||||
    setQueryParameters({
 | 
			
		||||
      ...queryParameters,
 | 
			
		||||
      query: value,
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  /* Change selected platforms */
 | 
			
		||||
  let onChangeSelectedPlatforms = (value) => {
 | 
			
		||||
    let newQueryParameters = {
 | 
			
		||||
    setQueryParameters({
 | 
			
		||||
      ...queryParameters,
 | 
			
		||||
      forecastingPlatforms: value,
 | 
			
		||||
    };
 | 
			
		||||
    onChangeSearchInputs(newQueryParameters);
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // Change show id
 | 
			
		||||
| 
						 | 
				
			
			@ -236,7 +241,6 @@ const CommonDisplay: React.FC<Props> = ({
 | 
			
		|||
  };
 | 
			
		||||
  let onClickForward = (whichResultToDisplayAndCapture: number) => {
 | 
			
		||||
    setWhichResultToDisplayAndCapture(whichResultToDisplayAndCapture + 1);
 | 
			
		||||
    // setTimeout(()=> {onClickForward(whichResultToDisplayAndCapture+1)}, 5000)
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  /* Final return */
 | 
			
		||||
| 
						 | 
				
			
			@ -300,7 +304,7 @@ const CommonDisplay: React.FC<Props> = ({
 | 
			
		|||
            </div>
 | 
			
		||||
            <div className="flex row-start-3 row-end-3 col-start-1 col-end-4 md:col-start-3 md:col-end-3 md:row-start-1 md:row-end-1 lg:col-start-3 lg:col-end-3 lg:row-start-1 lg:row-end-1 items-center justify-center mb-4">
 | 
			
		||||
              <SliderElement
 | 
			
		||||
                value={queryParameters.numDisplay}
 | 
			
		||||
                value={numDisplay}
 | 
			
		||||
                onChange={onChangeSliderForNumDisplay}
 | 
			
		||||
                displayFunction={displayFunctionNumDisplaySlider}
 | 
			
		||||
              />
 | 
			
		||||
| 
						 | 
				
			
			@ -329,31 +333,22 @@ const CommonDisplay: React.FC<Props> = ({
 | 
			
		|||
        })}
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      {displaySeeMoreHint ? (
 | 
			
		||||
      {displaySeeMoreHint &&
 | 
			
		||||
      (!results || (results.length != 0 && numDisplay < results.length)) ? (
 | 
			
		||||
        <div>
 | 
			
		||||
          <p
 | 
			
		||||
            className={`mt-4 mb-4 ${
 | 
			
		||||
              !results ||
 | 
			
		||||
              (results.length != 0 &&
 | 
			
		||||
                queryParameters.numDisplay < results.length)
 | 
			
		||||
                ? ""
 | 
			
		||||
                : "hidden"
 | 
			
		||||
            }`}
 | 
			
		||||
          >
 | 
			
		||||
          <p className="mt-4 mb-4">
 | 
			
		||||
            {"Can't find what you were looking for?"}
 | 
			
		||||
            <span
 | 
			
		||||
              className={`cursor-pointer text-blue-800 ${
 | 
			
		||||
                !results ? "hidden" : ""
 | 
			
		||||
              }`}
 | 
			
		||||
              onClick={() => {
 | 
			
		||||
                setQueryParameters({
 | 
			
		||||
                  ...queryParameters,
 | 
			
		||||
                  numDisplay: queryParameters.numDisplay * 2,
 | 
			
		||||
                });
 | 
			
		||||
                setNumDisplay(numDisplay * 2);
 | 
			
		||||
              }}
 | 
			
		||||
            >
 | 
			
		||||
              {" Show more, or"}
 | 
			
		||||
            </span>{" "}
 | 
			
		||||
              {" Show more,"}
 | 
			
		||||
            </span>
 | 
			
		||||
            {" or "}
 | 
			
		||||
            <a
 | 
			
		||||
              href="https://www.metaculus.com/questions/create/"
 | 
			
		||||
              className="cursor-pointer text-blue-800 no-underline"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
import searchWithAlgolia from "./searchWithAlgolia.js";
 | 
			
		||||
import searchGuesstimate from "./searchGuesstimate.js";
 | 
			
		||||
import searchGuesstimate from './searchGuesstimate.js';
 | 
			
		||||
import searchWithAlgolia from './searchWithAlgolia.js';
 | 
			
		||||
 | 
			
		||||
export default async function searchAccordingToQueryData(queryData) {
 | 
			
		||||
  let results = [];
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user