This is an automated email from the ASF dual-hosted git repository.
dengliming pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu-dashboard.git
The following commit(s) were added to refs/heads/master by this push:
new f674661b Fix isloading never resetting on the exception trigger page
(#663)
f674661b is described below
commit f674661bf61d063881c94df26cc4f0b1c12fa302
Author: Anay Parwal <[email protected]>
AuthorDate: Sat Sep 26 00:27:57 2026 -0400
Fix isloading never resetting on the exception trigger page (#663)
* Fix isloading never resetting on the exception trigger page
TriggerException tracked loading in local component state, set it to
true on click, and never reset it; meanwhile the error model's
`trigger` reducer dropped the (unused) `isloading` field from state.
Switches the component to the standard `loading.effects["error/query"]`
pattern already used throughout the codebase (e.g. GlobalHeader,
BasicLayout, most System/* pages). This is tracked by the dva-loading
plugin and resets automatically when the effect finishes, including
on failure, so the spinner can no longer get stuck. Also removes the
now-dead `isloading` field from the error model's state, since nothing
referenced it besides the buggy local flag.
Closes #653
* Coerce isloading to boolean; add regression test
Before the first dispatch, dva-loading's `effects` map is empty, so
`loading.effects["error/query"]` is undefined rather than false.
Ant Design's Spin treats an undefined `spinning` prop as true, so the
trigger page showed a loading overlay on initial render before any
request had been made.
Coerces the mapped value to a boolean with `!!`, and adds a test that
renders the connected component (via a minimal fake store, following
the reviewer's own repro) covering the empty-effects, in-flight, and
finished states.
---
src/models/error.js | 1 -
src/routes/Exception/triggerException.js | 26 ++++++------
src/routes/Exception/triggerException.test.js | 57 +++++++++++++++++++++++++++
3 files changed, 70 insertions(+), 14 deletions(-)
diff --git a/src/models/error.js b/src/models/error.js
index f994b7df..3af7073c 100644
--- a/src/models/error.js
+++ b/src/models/error.js
@@ -23,7 +23,6 @@ export default {
state: {
error: "",
- isloading: false,
},
effects: {
diff --git a/src/routes/Exception/triggerException.js
b/src/routes/Exception/triggerException.js
index 96755c67..74c2b27a 100644
--- a/src/routes/Exception/triggerException.js
+++ b/src/routes/Exception/triggerException.js
@@ -18,23 +18,14 @@
import React, { PureComponent } from "react";
import { Button, Spin, Card } from "antd";
import { connect } from "dva";
+import PropTypes from "prop-types";
import styles from "./style.less";
-@connect((state) => ({
- isloading: state.error.isloading,
+@connect(({ loading }) => ({
+ isloading: !!loading.effects["error/query"],
}))
export default class TriggerException extends PureComponent {
- constructor(props) {
- super(props);
- this.state = {
- isloading: false,
- };
- }
-
triggerError = (code) => {
- this.setState({
- isloading: true,
- });
const { dispatch } = this.props;
dispatch({
type: "error/query",
@@ -45,7 +36,7 @@ export default class TriggerException extends PureComponent {
};
render() {
- const { isloading } = this.state;
+ const { isloading } = this.props;
return (
<Card>
<Spin spinning={isloading} wrapperClassName={styles.trigger}>
@@ -66,3 +57,12 @@ export default class TriggerException extends PureComponent {
);
}
}
+
+TriggerException.propTypes = {
+ isloading: PropTypes.bool,
+ dispatch: PropTypes.func.isRequired,
+};
+
+TriggerException.defaultProps = {
+ isloading: false,
+};
diff --git a/src/routes/Exception/triggerException.test.js
b/src/routes/Exception/triggerException.test.js
new file mode 100644
index 00000000..13c0f9c6
--- /dev/null
+++ b/src/routes/Exception/triggerException.test.js
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from "react";
+import { render } from "@testing-library/react";
+import { Provider } from "react-redux";
+import TriggerException from "./triggerException";
+
+function renderWithStore(state) {
+ const store = {
+ getState: () => state,
+ subscribe: () => () => {},
+ dispatch: () => {},
+ };
+ return render(
+ <Provider store={store}>
+ <TriggerException />
+ </Provider>,
+ );
+}
+
+describe("TriggerException", () => {
+ it("is not spinning on initial render, before any effect has run", () => {
+ // Before the first dispatch, dva-loading's `effects` map is empty, so
+ // `loading.effects["error/query"]` is undefined rather than false.
+ const { container } = renderWithStore({ loading: { effects: {} } });
+ expect(container.querySelector(".ant-spin-spinning")).toBeNull();
+ });
+
+ it("is spinning while the error/query effect is in flight", () => {
+ const { container } = renderWithStore({
+ loading: { effects: { "error/query": true } },
+ });
+ expect(container.querySelector(".ant-spin-spinning")).not.toBeNull();
+ });
+
+ it("is not spinning once the error/query effect has finished", () => {
+ const { container } = renderWithStore({
+ loading: { effects: { "error/query": false } },
+ });
+ expect(container.querySelector(".ant-spin-spinning")).toBeNull();
+ });
+});