Есть компонент, который выводит сообщения об ошибках
export class Snackbar extends React.Component {
constructor(props) {
super(props);
}
state = {
messages: []
}
addAlert(message, timeout = null) {
const uniqueId = Date.now();
this.setState({
messages: [{message, id: uniqueId, onClose: !timeout && this.closeAlert.bind(this)}].concat(this.state.messages)
}, () => {
if (timeout) {
setTimeout(() => {
this.setState({
messages: this.state.messages.filter( m => m.id !== uniqueId)
});
}, timeout);
}
});
}
closeAlert(id) {
this.setState({
messages: [...this.state.messages.filter(m => m.id !== id)]
})
}
render() {
return (
<div className="toast-container">
<div className="toast">
{this.state.messages && this.state.messages.map( m => <Alert key={m.id} alert={m} />)}
</div>
</div>
);
}
}
Есть его провайдер
import {Snackbar} from './Snackbar';
import AlertContext from './AlertContext';
export const AlertProvider = ({children}) => {
const snackbarRef = useRef();
const showAlert = (message = 'Button Pressed...') => {
snackbarRef.current.addAlert(message, 3000);
}
return (
<AlertContext.Provider value={{showAlert}}>
<Snackbar ref={snackbarRef} />
{children}
</AlertContext.Provider>
)
}
Все приложение обернуто в этот провайдер
function App() {
const routes = useRoutes();
return (
<AlertProvider>
<Router>
<div className="App">
<Nav />
<Test />
{routes}
</div>
</Router>
</AlertProvider>
);
}
Вот собственно компонент в котором по нажатии кнопки ошибка успешно отображается
export const Test = () => {
const {loading, request, error} = useHttp();
const [orders, setOrders] = useState(null);
const {showAlert} = useContext(AlertContext); //этот showAlert работает только в рендере
showAlert('error'); //в этом месте ошибка
useEffect( () => {
async function getOrder() {
try {
const data = await request(`/api/parser/`, 'GET');
setOrders(data);
} catch (e) {
//Вот в этом месте необходимо отобразить ошибку функцией showAlert
}
}
getOrder();
}, [request])
return (
<>
<button onClick={() => showAlert('Test alert useContext')}>Show test alert useContext</button>
<AlertContext.Consumer>
{({ showAlert }) => (
<button onClick={() => showAlert('Test alert')}>Show test alert</button>
)}
</AlertContext.Consumer>
</>
)
}
Как добавить вызов функции до рендера? Сейчас выходит ошибка
TypeError: Cannot read property 'addAlert' of undefined
И попутный вопрос: можно ли класс
Snackbar перевести в функициональный компонент и есть ли другой способ сделать подобный компонент для отображения сообщений?