Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix loading state on watch list page + better handling for reloads #39339

Merged

Conversation

alisonelizabeth
Copy link
Contributor

This PR fixes the loading state on the watch list view, removing it from the table and replacing it with the SectionLoading component. I also updated the use_request hook so that the loading state will only be set on the initial request.

FYI @silne30

@alisonelizabeth alisonelizabeth added Feature:Watcher non-issue Indicates to automation that a pull request should not appear in the release notes Team:Kibana Management Dev Tools, Index Management, Upgrade Assistant, ILM, Ingest Node Pipelines, and more labels Jun 20, 2019
@elasticmachine
Copy link
Contributor

Pinging @elastic/es-ui

@elasticmachine
Copy link
Contributor

💔 Build Failed

Copy link
Contributor

@cjcenizal cjcenizal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested locally, code LGTM! Just had one suggestion.

setIsLoading(true);

// Only set loading state to true and initial data on the first request
if (isInitialRequest) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this hook would be more flexible if it managed and exposed the isInitialRequest state and allowed the consumer to decide how to react to it, instead of encapsulating this type of logic. For example, if this was the hook:

export const useRequest = ({
  path,
  method,
  body,
  interval,
  initialData,
  processData,
}: UseRequest) => {
  const [error, setError] = useState<null | any>(null);
  const [isLoading, setIsLoading] = useState<boolean>(false);
  const [isInitialRequest, setIsInitialRequest] = useState<boolean>(true);
  const [data, setData] = useState<any>(initialData);

  // Tied to every render and bound to each request.
  let isOutdatedRequest = false;

  const createRequest = async (isInitialRequest = true) => {
    // Set a neutral state for a non-request.
    if (!path) {
      setError(null);
      setData(initialData);
      setIsLoading(false);
      return;
    }

    setError(null);
    setIsLoading(true);
    setIsInitialRequest(false);
    setData(initialData);

    const { data: responseData, error: responseError } = await sendRequest({
      path,
      method,
      body,
    });

    // Don't update state if an outdated request has resolved.
    if (isOutdatedRequest) {
      return;
    }

    setError(responseError);
    setData(processData && responseData ? processData(responseData) : responseData);
    setIsLoading(false);
  };

  useEffect(
    () => {
      function cancelOutdatedRequest() {
        isOutdatedRequest = true;
      }

      createRequest();

      if (interval) {
        const intervalRequest = setInterval(createRequest, interval);

        return () => {
          cancelOutdatedRequest();
          clearInterval(intervalRequest);
        };
      }

      // Called when a new render will trigger this effect.
      return cancelOutdatedRequest;
    },
    [path]
  );

  return {
    error,
    isLoading,
    isInitialRequest,
    data,
    createRequest,
  };
};

Then in watch_visualization.tsx we could do something like this (warning, I haven't tested this)"

  const {
    isLoading,
    isInitialRequest,
    data: watchVisualizationData,
    error,
    createRequest: reload,
  } = getWatchVisualizationData(watchWithoutActions, visualizeOptions);

/* ... */

  if (isLoading && isInitialRequest) {
    return (
      <EuiEmptyPrompt
        title={<EuiLoadingChart size="xl" />}
        body={
          <EuiText color="subdued">
            <FormattedMessage
              id="xpack.watcher.sections.watchEdit.loadingWatchVisualizationDescription"
              defaultMessage="Loading watch visualization…"
            />
          </EuiText>
        }
      />
    );
  }

WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cjcenizal I like this idea. I think the one issue is that we also don't want to set the data back to initialData on subsequent requests.

Copy link
Contributor

@cjcenizal cjcenizal Jun 21, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. I tried to account for that with setIsInitialRequest(false); a few lines down inside of the createRequest function in the useRequest hook -- does that address the problem?

Copy link
Contributor Author

@alisonelizabeth alisonelizabeth Jun 21, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would still set the data to initialData every time (but I might be missing something).

setError(null);
setIsLoading(true);
setIsInitialRequest(false);
setData(initialData);

Also, we’re actually setting the initial state of isLoading to false, so I don’t think this check would work:

if (isLoading && isInitialRequest) {}

Not opposed to this approach, just trying to think through how it would work :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cjcenizal I'm going to go ahead and merge this in as is. I will revisit if we end up needing it to be more flexible!

@elasticmachine
Copy link
Contributor

💔 Build Failed

@alisonelizabeth
Copy link
Contributor Author

retest

@elasticmachine
Copy link
Contributor

💚 Build Succeeded

@elasticmachine
Copy link
Contributor

💚 Build Succeeded

@alisonelizabeth alisonelizabeth merged commit 29f9c56 into elastic:watcher-port Jun 24, 2019
@alisonelizabeth alisonelizabeth deleted the watcher-loading-state branch June 24, 2019 14:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature:Watcher non-issue Indicates to automation that a pull request should not appear in the release notes Team:Kibana Management Dev Tools, Index Management, Upgrade Assistant, ILM, Ingest Node Pipelines, and more
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants