需要从反应中的动作调用警报消息组件

Need to call an alert message component from action in react

我创建了一个通用组件并将其导出,我需要根据 API 的结果调用该组件。如果 api 成功,则警报消息组件将调用消息“已成功更新”。错误然后显示错误消息。

正在调用服务方法。我们有什么办法可以这样做吗?是否可以在动作中调用组件

不能在action中调用Component,但是可以使用state调用render中的Component,使用条件渲染或者Alert Component的状态,比如isShow。

你有很多选择。

1。 Redux

如果你是 Redux 的粉丝,或者你的项目已经在使用 Redux,你可能想这样做。

首先声明slice、provider和hook

const CommonAlertSlice = createSlice({
    name: 'CommonAlert',
    initialState : {
        error: undefined
    },
    reducers: {
        setError(state, action: PayloadAction<string>) {
            state.error = action.payload;
        },
        clearError(state) {
            state.error = undefined;
        },
    }
});

export const CommonAlertProvider: React.FC = ({children}) => {
    const error = useSelector(state => state['CommonAlert'].error);
    const dispatch = useDispatch();
    return <>
        <MyAlert 
            visible={error !== undefined} 
            body={error} onDismiss={() => 
            dispatch(CommonAlertSlice.actions.clearError())} />
        {children}
    </>
}

export const useCommonAlert = () => {
    const dispatch = useDispatch();
    return {
        setError: (error: string) => dispatch(CommonAlertSlice.actions.setError(error)),
    }
}

然后像这样使用它。

const App: React.FC = () => {
    return <CommonAlertProvider>
        <YourComponent />
    </CommonAlertProvider>
}

const YourComponent: React.FC = () => {
    const { setError } = useCommonAlert();
    useEffect(() => {
        callYourApi()
            .then(...)
            .catch(err => {
                setError(err.message);
            });
    });

    return <> ... </>
}

2。反应上下文

如果你喜欢内置的 React Context,你可以像这样让它更简单。

const CommonAlertContext = createContext({
    setError: (error: string) => {}
});

export const CommonAlertProvider: React.FC = ({children}) => {
    const [error, setError] = useState<string>();
    return <CommonAlertContext.Provider value={{
               setError
           }}>
        <MyAlert 
            visible={error !== undefined} 
            body={error} onDismiss={() => setError(undefined)} />
        {children}
    </CommonAlertContext.Provider>
}

export const useCommonAlert = () => useContext(CommonAlertContext);

然后以与 Redux 示例中完全相同的方式使用它。

3。提供渲染方法的钩子

这个选项最简单。

export const useAlert = () => {
    const [error, setError] = useState<string>();
    return {
        setError,
        renderAlert: () => {
            return <MyAlert 
                      visible={error !== undefined} 
                      body={error} onDismiss={() => setError(undefined)} />
        }
    }
}

使用它。

const YourComponent: React.FC = () => {
    const { setError, renderAlert } = useAlert();

    useEffect(() => {
        callYourApi()
            .then(...)
            .catch(err => {
                setError(err.message);
            });
    });

    return <> 
            {renderAlert()} 
            ... 
    </>
}

在Antd库中看到了类似的方案,就是这样实现的

codesandbox link

App.js

import "./styles.css";
import alert from "./alert";

export default function App() {
  const handleClick = () => {
    alert();
  };
  return (
    <div className="App">
      <button onClick={handleClick}>Show alert</button>
    </div>
  );
}

警报功能

import ReactDOM from "react-dom";
import { rootElement } from ".";
import Modal from "./Modal";

export default function alert() {
  const modalEl = document.createElement("div");
  rootElement.appendChild(modalEl);

  function destroy() {
    rootElement.removeChild(modalEl);
  }

  function render() {
    ReactDOM.render(<Modal destroy={destroy} />, modalEl);
  }

  render();
}

你的模态组件

import { useEffect } from "react";

export default function Modal({ destroy }) {
  useEffect(() => {
    return () => {
      destroy();
    };
  }, [destroy]);

  return (
    <div>
      Your alert <button onClick={destroy}>Close</button>
    </div>
  );
}