Как в reactstrap настроить предупреждающее сообщение и видимое состояние дочернего компонента? - PullRequest
0 голосов
/ 13 июля 2020

Я использую React 16.13.0 и пытаюсь использовать компонент Reactstrap Alert для отображения сообщений при отправке определенных форм. Я разместил компонент Alert там, где я хочу, в своем шаблоне приложения ...

import { Alert } from 'reactstrap';

function App() {
  return (
    <Router>
      <div className="App">
        <nav className="navbar navbar-expand-lg navbar-light fixed-top">
          <div className="container">
            <Link className="navbar-brand" to={"/add"}>
              Chicommons
            </Link>
            <NavBar />
          </div>
        </nav>

        <div className="auth-wrapper">
          <div className="auth-inner">
            <Alert color="info" isOpen={this.state.visible} >
              I am an alert and I will disappear in 2sec.!
            </Alert>
            <Switch>
              <Route exact path="/" component={Add} />
              <Route path="/add" component={Add} />
              <Route path="/edit/:id" component={Edit} />
              <Route path="/search" component={Search} />
              <Route path="/:coop_id/people" component={AddPerson} />
              <Route path="/:coop_id/listpeople" component={ListPeople} />
            </Switch>
          </div>
        </div>
      </div>
    </Router>
  );
}

export default App;

У меня проблемы с парой вещей. Один из моих компонентов формы, src / container / FormContainer.jsx, имеет этот обработчик отправки ...

  const handleFormSubmit = (e) => {
    e.preventDefault();
    // Make a copy of the object in order to remove unneeded properties
    const NC = JSON.parse(JSON.stringify(coop));
    delete NC.addresses[0].country;

    const url = coop.id ? REACT_APP_PROXY + "/coops/" + coop.id : REACT_APP_PROXY + "/coops/";
    const method = coop.id ? "PATCH" : "POST";
    fetch(url, {
      method: method,
      body: JSON.stringify(NC),
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json",
      },
    })
      .then((response) => {
        if (response.ok) {
          return response.json();
        } else {
          throw response;
        }
      })
      .then((data) => {
        const result = data;
        history.push({
          pathname: "/" + result.id + "/people",
          state: { coop: result },
        });
        window.scrollTo(0, 0);

        /** Would like to place alert here **/

      })
      .catch((err) => {
        console.log(err);
        err.text().then((errorMessage) => {
          setErrors(JSON.parse(errorMessage));
        });
      });
  };

Я хотел бы включить предупреждение responsestrap с настраиваемым сообщением, созданным в указанном выше обработчике. Однако я не знаю, как контролировать состояние родительского компонента. Я предполагаю, что мне придется создать какое-то состояние сообщения в родительском компоненте, а также контролировать видимое состояние, которое у меня уже есть, но я не знаю, как это сделать из дочернего компонента.

Ответы [ 2 ]

0 голосов
/ 16 июля 2020

Вы можете создать контекст, который обеспечивает легкий доступ к предупреждению в любом месте приложения.

AlertProvider.js

import React, { useState, useCallback, useContext, createContext } from 'react'

const AlertContext = createContext()

export function AlertProvider(props) {
  const [open, setOpen] = useState(false)
  const [message, setMessage] = useState()


  const handleClose = useCallback(() => {
    setOpen(false)
  }, [setOpen])

  const handleOpen = useCallback(message => {
    setMessage(message)
    setOpen(true)
  }, [setMessage, setOpen])
    
  return (
    <AlertContext.Provider value={[handleOpen, handleClose]}>
      {props.children}
      <Alert color="info" isOpen={open} toggle={handleClose} >
        {message}
      </Alert>
    </AlertContext.Provider>
  )
}


export function useAlert() {
  const context = useContext(AlertContext);
  if (!context)
    throw new Error('`useAlert()` must be called inside an `AlertProvider` child.')

  return context
}

Обновите App.js

import { Alert } from 'reactstrap';
import { AlertProvider } from './AlertProvider';

function App() {
  return (
    <AlertProvider>
      <Router>
        <div className="App">
          <nav className="navbar navbar-expand-lg navbar-light fixed-top">
            <div className="container">
              <Link className="navbar-brand" to={"/add"}>
                Chicommons
              </Link>
              <NavBar />
            </div>
          </nav>

          <div className="auth-wrapper">
            <div className="auth-inner">
              <Switch>
                <Route exact path="/" component={Add} />
                <Route path="/add" component={Add} />
                <Route path="/edit/:id" component={Edit} />
                <Route path="/search" component={Search} />
                <Route path="/:coop_id/people" component={AddPerson} />
                <Route path="/:coop_id/listpeople" component={ListPeople} />
              </Switch>
            </div>
          </div>
        </div>
      </Router>
    </AlertProvider>
  );
}

export default App;

Затем вы можете использовать это в функциональных компонентах:

import React, { useEffect } from 'react'
import { useAlert } from './AlertProvider'

function MyComponent() {
  const [open, close] = useAlert();

  useEffect(() => {
    // when some condition is met
      open("Hi") // closable with the toggle, or in code via close()
  })
}

Здесь используется повелительное настроение открывать и закрывать, вызывая open() и close(). Если вам нужен декларативный настрой, контекст должен вместо этого напрямую возвращать функции setMessage и setOpen.

Вы также можете поэкспериментировать, чтобы разместить компонент предупреждения в другом месте.

0 голосов
/ 16 июля 2020

Чуть ниже function App() {. добавьте:

const [alertMessage, setAlertMessage] = React.useState("")

И измените свое предупреждение на:

<Alert color="info" isOpen={alertMessage!=""} toggle={()=>setAlertMessage("")} >
    {alertMessage}
</Alert>

И тогда я не знаю, как устроена остальная часть вашего приложения, но вы хотите передать setAlertMessage функцию в handleFormSubmit в качестве обратного вызова и вызовите ее в / около setErrors

...