I am new to react and I want to implement a notification popup showing either the error or success from an api response inside another component. This is the component I have for the notification with animation included where later I plan to have the props.message have the error message content:
export function MessagesComponent(props) {
console.log("Notification triggered")
let [message, setMessage] = useState("This is the error message")
let [classes, setClasses] = useState('animate__bounceInDown error-message-color ')
let [signClasses, setSignClasses] = useState(' ')
useEffect(() => {
setSignClasses(' error-sign-color')
},[])
useEffect(() => {
let timer1 = setTimeout(() => setClasses('animate__bounceOutLeft error-message-color'), 3000)
return () => {
clearTimeout(timer1)
}
})
return (
<>
<div className={classes.concat(' messages-wrapper animate__animated error-message-color')} id="messages-wrapper">
<div className={signClasses.concat(" message-sign")}><i className="bi bi-x-lg"></i></div>
<div className="messages" id="messages">{message}</div>
</div>
</>
)
}
It just makes it drop from the bottom and after some time it goes away. I have this in the index html document along my list component for testing and styling:
<div id="messages-component"></div>
<div id="categories-list"></div>
This works and the animation triggers when I reload the page but now I want it to trigger only when there is an error. I have a category list that can be edited and the list component renders the following category component for each category the api fetches:
export function Category(props) {
let { category } = props
let [categories, setCategory] = useState(category)
let inputRef = React.createRef()
let [updateStyle, setUpdateStyle] = useState('d-none')
function handleUpdateBackend() {
let currentValue = inputRef.current.value
let handleUpdateBackend = (response, status) => {
if (status === 200) {
setCategory(response)
}
else {
//Call the notification component
}
}
apiPatchCategory(category.id, handleUpdateBackend, currentValue)
setUpdateStyle('d-none')
...
Everything works fine and I had an alert()
function for the message error displaying but I want it to be more personalized. I am not sure how to call the component to render only when the else statement executes. The reason I built a component is because I plan to reuse this in other areas where messages are needed. I tried calling it inside the else statement directly but no luck so there is something I am missing. This is what I have but as mentioned it triggers on reload:
CodePudding user response:
You cannot call a component anywhere in your code, except in the render method of another React component. I suggest the following approach:
- Create a React container component that lives somewhere in your app, which will serve to receive and display messages, and to animate them.
- Create a message service that you can call to dispatch a new message.
You'll need the message service to expose a static method that you can call to create a new message. The container component, meanwhile, subscribes to the message services when it is created.
Here is some skeleton code for a message service:
/**
* ToastService is used to create Toasts.
*
* To create a Toast, do
*
* ToastService.toast(ReactNode, duration in ms[optional])
*/
class ToastService {
private static subscriber: IToastSubscriber = null;
/**
* Subscribe a ToastContainer to the ToastService.
* There can only be a single subscriber (it does not
* make sense to show toasts in more than one place).
*/
public static subscribe(subscriber: IToastSubscriber) {
ToastService.subscriber = subscriber;
}
/**
* Create a new Toast.
* @param message Message to show. This is a React Node.
* @param duration (Optional) Toast duration in ms.
*/
public static toast(message: React.ReactNode, duration?: number) {
// Toasts are not created if there is no ToastContainer subscribed
// to the ToastService.
if(ToastService.subscriber == null) return;
ToastService.subscriber.toast(message, duration);
}
}
You would call this message service from your Category
function:
ToastService.toast("An error occurred.");
For the message container, your React component might look like this (I'll leave most of the implementation details out):
class ToastContainer implements IToastSubscriber {
constructor(props) {
ToastService.subscribe(this);
this.state = { messages: {} };
}
public toast(message: React.ReactNode, duration?: number) {
// Add message to state.messages
}
...
render() {
return(
// For each message in state.messages, render a message component.
);
}
}
You'd use the duration of each message to eventually remove it from your list of messages.
CodePudding user response:
You can use ternary opeator to Display that message Component inside ur JSX
{someCondition ? <ErrorMessageComponent /> : null} // This will render the component when there is an error
OR
{someCondition && <ErrorMessageComponent />} //Same thing
but make sure that u take care of ur removing error message properly otherwise it will alway's shown th div