Home > Software design >  Need to call an alert message component from action in react
Need to call an alert message component from action in react

Time:01-18

I've created a common component and exported it, i need to call that component in action based on the result from API. If the api success that alert message component will call with a message as "updated successfully". error then show with an error message.

calling service method in action. is there any way we can do like this? is it possible to call a component in action

CodePudding user response:

You can't call a Component in action, but you can use state for call a Component in render, using conditional rendering or state of Alert Component such as isShow.

CodePudding user response:

I saw the similar solution in Antd library, it was implemented like that

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>
  );
}

alert function

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();
}

Your modal component

import { useEffect } from "react";

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

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

CodePudding user response:

You have many options.

1. Redux

If you are a fan of Redux, or your project already use Redux, you might want to do it like this.

First declare the slice, provider and 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)),
    }
}

And then use it like this.

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

If you like the built-in React Context, you can make it more simpler like this.

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);

And then use it the exact same way as in the Redux example.

3. A Hook Providing a Render Method

This option is the simplest.

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

Use it.

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

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

    return <> 
            {renderAlert()} 
            ... 
    </>
}
  •  Tags:  
  • Related