Рендеринг условной навигации в React

#javascript #reactjs #react-router #jsx

#javascript #reactjs #react-маршрутизатор #jsx

Вопрос:

Я создаю простое приложение react, используя React версии 16.7 и MDB (Material Design для начальной загрузки). react-router-dom обрабатывает мою систему маршрутизации. Я хочу, чтобы моя панель навигации была прозрачной на главной странице, а на других страницах я хочу, чтобы она была темной. Мой код выглядит следующим образом:

App.js

 class App extends Component {

state = {
    collapseID: ""
}

toggleCollapse = collapseID => () =>
    this.setState(prevState => ({
        collapseID: prevState.collapseID !== collapseID ? collapseID : ""
    }));

closeCollapse = collapseID => () =>
    this.state.collapseID === collapseID amp;amp; this.setState({ collapseID: "" });

render() {

    const overlay = (
        <div
            id="sidenav-overlay"
            style={{ backgroundColor: "transparent" }}
            onClick={this.toggleCollapse("mainNavbarCollapse")}
        />
    );

    const { collapseID } = this.state;

    return (
        <Router>
            <div className="flyout">
                <MDBNavbar color="elegant-color-dark" dark expand="md" fixed="top" scrolling transparent>
                    <MDBContainer>
                        <MDBNavbarBrand href="/">
                            <img src={Logo} height="50" alt="Logo" />
                        </MDBNavbarBrand>
                        <MDBNavbarToggler onClick={this.toggleCollapse("mainNavbarCollapse")} />
                        <MDBCollapse id="mainNavbarCollapse" isOpen={this.state.collapseID} navbar>
                            <MDBNavbarNav right>
                                <MDBNavItem>
                                    <MDBNavLink exact to="/" onClick={this.closeCollapse("mainNavbarCollapse")} >
                                        Home
                                    </MDBNavLink>
                                </MDBNavItem>
                                <MDBNavItem>
                                    <MDBNavLink onClick={this.closeCollapse("mainNavbarCollapse")} to="/about" >
                                        About
                                    </MDBNavLink>
                                </MDBNavItem>
                                <MDBNavItem>
                                    <MDBNavLink onClick={this.closeCollapse("mainNavbarCollapse")} to="/products">
                                        Products
                                    </MDBNavLink>
                                </MDBNavItem>
                                <MDBNavItem>
                                    <MDBNavLink onClick={this.closeCollapse("mainNavbarCollapse")} to="/trading">
                                        Trading
                                    </MDBNavLink>
                                </MDBNavItem>
                                <MDBNavItem>
                                    <MDBNavLink onClick={this.closeCollapse("mainNavbarCollapse")} to="/contact">
                                        Contact
                                    </MDBNavLink>
                                </MDBNavItem>
                            </MDBNavbarNav>
                        </MDBCollapse>
                    </MDBContainer>
                </MDBNavbar>
                {collapseID amp;amp; overlay}
                <main style={{ marginTop: "0" }}>
                    <Routes />
                </main>
            </div>
        </Router>
    );
  }
}

export default App;
  

Routes.js

 class Routes extends React.Component {
render() {
    return (
        <Switch>
            <Route exact path="/" component={Home} />
            <Route exact path="/about" component={About} />
            <Route exact path="/products" component={Products} />
            <Route exact path="/trading" component={Trading} />
            <Route exact path="/contact" component={Contact} />
            <Route
                render = {function () {
                    return <h1 className="text-center m-5">Page Not Found</h1>;
                }}
            />
        </Switch>
    );
  }
}

export default Routes;
  

In App.js , как вы можете видеть, <MDBNavbar color="elegant-color-dark" dark expand="md" fixed="top" scrolling transparent> имеет атрибут transparent . Я хочу, чтобы это было только на главной странице. На других страницах это будет выглядеть так: <MDBNavbar color="elegant-color-dark" dark expand="md" fixed="top" scrolling> .

Я пытался использовать states и props , но безуспешно. Как я могу решить эту проблему?

Заранее спасибо.

Ответ №1:

Вы можете использовать withRouter HOC из react-router ( https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/withRouter.md ) для получения location реквизитов в панели навигации, извлеченных как отдельный компонент. Это более или менее дало бы это (за вычетом реквизитов, отсутствующих на панели навигации):

                const NavBar = ({location, collapseID, closeCollapse, toggleCollapse}) => <MDBNavbar color={location.pathname === "home"? "elegant-color-dark": ""} dark expand="md" fixed="top" scrolling transparent>
                    <MDBContainer>
                        <MDBNavbarBrand href="/">
                            <img src={Logo} height="50" alt="Logo" />
                        </MDBNavbarBrand>
                        <MDBNavbarToggler onClick={toggleCollapse("mainNavbarCollapse")} />
                        <MDBCollapse id="mainNavbarCollapse" isOpen={collapseID} navbar>
                            <MDBNavbarNav right>
                                <MDBNavItem>
                                    <MDBNavLink exact to="/" onClick={closeCollapse("mainNavbarCollapse")} >
                                        Home
                                    </MDBNavLink>
                                </MDBNavItem>
                                <MDBNavItem>
                                    <MDBNavLink onClick={closeCollapse("mainNavbarCollapse")} to="/about" >
                                        About
                                    </MDBNavLink>
                                </MDBNavItem>
                                <MDBNavItem>
                                    <MDBNavLink onClick={closeCollapse("mainNavbarCollapse")} to="/products">
                                        Products
                                    </MDBNavLink>
                                </MDBNavItem>
                                <MDBNavItem>
                                    <MDBNavLink onClick={closeCollapse("mainNavbarCollapse")} to="/trading">
                                        Trading
                                    </MDBNavLink>
                                </MDBNavItem>
                                <MDBNavItem>
                                    <MDBNavLink onClick={closeCollapse("mainNavbarCollapse")} to="/contact">
                                        Contact
                                    </MDBNavLink>
                                </MDBNavItem>
                            </MDBNavbarNav>
                        </MDBCollapse>
                    </MDBContainer>
                </MDBNavbar>

const NavBarWithRouter = withRouter(NavBar) 

class App extends Component {

state = {
    collapseID: ""
}

toggleCollapse = collapseID => () =>
    this.setState(prevState => ({
        collapseID: prevState.collapseID !== collapseID ? collapseID : ""
    }));

closeCollapse = collapseID => () =>
    this.state.collapseID === collapseID amp;amp; this.setState({ collapseID: "" });

render() {

    const overlay = (
        <div
            id="sidenav-overlay"
            style={{ backgroundColor: "transparent" }}
            onClick={this.toggleCollapse("mainNavbarCollapse")}
        />
    );

    const { collapseID } = this.state;

    return (
        <Router>
            <div className="flyout">
                <NavBarWithRouter toggleCollapse={this. toggleCollapse} closeCollapse={this.closeCollapse} collapseID={collapseID} />
                {collapseID amp;amp; overlay}
                <main style={{ marginTop: "0" }}>
                    <Routes />
                </main>
            </div>
        </Router>
    );
  }
}

export default App;

  

Комментарии:

1. Это работает, но панель навигации не может видеть collapseID и closeCollapse()

2. Передайте их в качестве реквизитов в NavBarWithRouter

3. Можете ли вы показать мне, я новичок. Мне нужно collapseID , closeCollapse() и overlay в моей панели навигации.

4. Спасибо. Что мне делать, если я преобразовываю переменную navbar в компонент react (например Navbar.js )? Я думаю, что я должен получить реквизиты в конструкторе навигационной панели?

5. Не обязательно — посмотрите на мой код, у NavBar нет конструктора. У вас может быть функциональный компонент (обычная функция JS), где реквизитами являются аргументы функции: reactjs.org/docs/components-and-props.html

Ответ №2:

Вы можете использовать window.location.pathname и сопоставить его с маршрутом домашней страницы, чтобы условно передавать реквизиты.

Определите объект props, который вы хотите передать, предпочтительно в componentDidMount App.js :

 let homePageProps = {};
if (window.location.pathname === "/") {
  homePageProps.transparent = "transparent";
}
  

Затем распространите его.

 <MDBNavbar color="elegant-color-dark" dark expand="md" fixed="top" scrolling {...homePageProps}>
  

Комментарии:

1. Это не сработало. Если я определяю homePageProps внутри componentDidMount , возникает другая ошибка: неопределенная переменная. Если определить его снаружи, он не работает.

2. Какая переменная не определена?

3. @JibinJoseph, homePageProps

4. Вам не кажется, что это действительно забавная ошибка? Даже если вы объявите это в componentDidMount , это должно сработать.

5. Да, конечно. Я смог использовать его с this ключевым словом, но когда я перехожу на другую страницу, панель навигации остается прежней. DOM не был обновлен.