Reactjs - маршрутизация на разные вкладки - PullRequest
0 голосов
/ 06 июля 2018

В моем проекте есть HeaderComponent и BodyComponent. Это TabComponent из HeaderComponent:

TabComponent

import React, {Component} from 'react'
import Context from '../../provider'
import {Nav, NavItem, NavLink} from 'reactstrap'
import {Redirect} from 'react-router-dom'
import classnames from 'classnames'

export default class TabComponent extends Component {
    render() {
        return (
            <Context.Consumer>
                {context => (
                    <Nav tabs color='primary'>
                        <NavItem>
                            <NavLink
                                className={classnames({ active: context.activeTab === '1' })}
                                onClick={() => { context.toggleTab('1'); }}
                            >
                            Home
                            </NavLink>
                        </NavItem>
                        <NavItem>
                            <NavLink
                                className={classnames({ active: context.activeTab === '2' })}
                                onClick={() => { context.toggleTab('2'); }}
                            >
                            Popular
                            </NavLink>
                        </NavItem>
                        <NavItem>
                            <NavLink
                                className={classnames({ active: context.activeTab === '3' })}
                                onClick={() => { context.toggleTab('3'); }}
                            >
                            All
                            </NavLink>
                        </NavItem>                
                    </Nav>
                )}
            </Context.Consumer>
        )
    }
}

BodyComponent

import React, {Component} from 'react'
import Context from '../provider'
import SwitchTab from './OtherComponents/SwitchTab'
import { BrowserRouter, Route, Redirect } from "react-router-dom";

export default class BodyComponent extends Component {
    render() {
        return (
            <Context.Consumer>
                {context => {
                    return (
                        <React.Fragment>
                            <BrowserRouter>
                                <React.Fragment>
                                    <Route exact path='/' render={() => <Redirect to='/home/' /> } />
                                    <Route eaxt path='/home/' render={() => context.activetab='1'} />
                                    <Route eaxt path='/popular/' render={() => context.activetab='2'} />
                                    <Route eaxt path='/all/' render={() => context.activetab='3'} />
                                </React.Fragment>
                            </BrowserRouter>
                            <SwitchTab />
                        </React.Fragment>
                    )
                }}
            </Context.Consumer>
        )
    }
}

Это мой provider.js с Context

import React, {Component} from 'react';

const Context = React.createContext();

class Provider extends Component {
  state = {

    loggedIn: false,
    username: '',
    password: '',
    loginModalOpen: false,
    signupModalOpen: false,
    navbarOpen: false,
    activeTab: '3',

    toggleLoggedIn: () => {
      this.setState({loggedIn: !this.state.loggedIn});
    },

    toggleLoginModal: () => {
      this.setState({loginModalOpen: !this.state.loginModalOpen});
    },

    toggleSignupModal: () => {
      this.setState({signupModalOpen: !this.state.signupModalOpen});
    },


    toggleNavbar: () => {
      this.setState({navbarOpen: !this.state.navbarOpen})
    },

    toggleTab: (tab) => {
      if(this.state.activeTab !== tab) {
        this.setState({activeTab: tab});
      }
    }
  }

  render() {
    return (
        <Context.Provider value={this.state}>
            {this.props.children}
        </Context.Provider>
    )
  }
}

export {Provider};
export default Context;

А это мой SwitchTab

import React, {Component} from 'react'
import Context from "../../../provider";
import { Container, TabContent, TabPane } from "reactstrap";
import Home from '../../Content/Home'
import Popular from '../../Content/Popular'
import All from '../../Content/All'

export default class SwitchTab extends Component {
    render() {
        return (
            <Context.Consumer>
                {context => {
                    return (
                        <Container>
                            <TabContent activeTab={context.activeTab}>
                                <TabPane tabId="1">
                                    <Home />
                                </TabPane>
                                <TabPane tabId="2">
                                    <Popular />
                                </TabPane>
                                <TabPane tabId="3">
                                    <All />
                                </TabPane>
                            </TabContent>   
                        </Container>
                    )
                }}
            </Context.Consumer>
        )
    }
}

Функциональность, которую я хочу достичь:

  • Всякий раз, когда URL-адрес «/», перенаправьте на «/home/».
  • Всякий раз, когда URL-адрес '/ home /', измените activeTab с Context и сделать SwitchTab повторной визуализации, чтобы получить вкладку home открыт.

Текущее рабочее состояние: когда я нажимаю на вкладку, содержимое меняется, но URL остается как /home/. Если изменить URL-адрес на /popular/ или /all/, содержимое не изменится.

1 Ответ

0 голосов
/ 06 июля 2018

В ошибке четко указано, что не так с вашей проблемой, вам нужно обернуть свои маршруты в div, так как Router принимает только один дочерний элемент.

Также для установки состояния в провайдере необходимо использовать setState или предоставить обработчик

class Provider extends Component {
  state = {

    loggedIn: false,
    username: '',
    password: '',
    loginModalOpen: false,
    signupModalOpen: false,
    navbarOpen: false,
    activeTab: '3',

    setActiveTab: (tab) => {
       this.setState({activeTab: tab});
    }

    toggleLoggedIn: () => {
      this.setState({loggedIn: !this.state.loggedIn});
    },

    toggleLoginModal: () => {
      this.setState({loginModalOpen: !this.state.loginModalOpen});
    },

    toggleSignupModal: () => {
      this.setState({signupModalOpen: !this.state.signupModalOpen});
    },


    toggleNavbar: () => {
      this.setState({navbarOpen: !this.state.navbarOpen})
    },

    toggleTab: (tab) => {
      if(this.state.activeTab !== tab) {
        this.setState({activeTab: tab});
      }
    }
  }

  render() {
    return (
        <Context.Provider value={this.state}>
            {this.props.children}
        </Context.Provider>
    )
  }
}

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

class Handler extends React.Component {
   componentDidMount() {
      this.props.setActiveTab(this.props.activeTab);
   }
   render() {
     return null;
   }
}

и ваша конфигурация маршрутизатора будет выглядеть как

<BrowserRouter>
   <div>
      <Route exact path='/' render={() => <Redirect to='/home/' /> } />
      <Route exact path='/home/' render={() => <Handler setActiveTab={setActiveTab} activeTab={'1'} />}/>
      <Route exact path='/popular/' render={() => <Handler setActiveTab={setActiveTab} activeTab={'2'} />}/>
      <Route exact path='/all/' render={() => <Handler setActiveTab={setActiveTab} activeTab={'3'} />}/>
   </div>
</BrowserRouter>
...