Реакция - при переключении между профилями отображаются условия рендеринга для предыдущего профиля. - PullRequest
0 голосов
/ 08 июня 2018

Я создаю приложение React, в котором я хочу показать несколько профилей.
На странице профиля я хочу использовать вкладки для отображения информации о профиле: например, имени и номера.
Для переключения междупрофили, я добавил предыдущую и следующую кнопку.

И у меня возникает следующая проблема:

Если я переключил вкладки профиля с «Имя» на «Номер», и после этого я перешел к следующему профилю,Я вижу следующий профиль с уже активной вкладкой «Номер».Но я ожидаю увидеть статус профиля с именем по умолчанию.

И та же проблема, если я отсортировал информацию на вкладке профиля, а затем перешел к следующему профилю, я уже получил отсортированную информацию для следующего профиля.

Не могу понять, где я ошибся, и буду очень благодарен за помощь.

// my profiles.json
let profiles = [{"name":"John", "count": 2}, {"name":"Kitty", "count": 3}, {"name":"Ji", "count": 4}]

const ProfileName = (props) => (
    <div><h1>{props.name}</h1></div>
)

const ProfileCount = (props) => (
    <div><h1>{props.count}</h1></div>
)

const Prev = (props) => (
  <button onClick={props.toggle} disabled={props.active}>Prev</button>
)

const Next = (props) => (
  <button onClick={props.toggle} disabled={props.active}>Next</button>
)

class Tab extends React.Component {
  constructor(props, context) {
    super(props, context)
  }

  handleTabClick(e) {
    e.preventDefault()
    this.props.onClick(this.props.tabIndex)
  }

  render() {
    return (
      <li className='tab'>
        <a className={`tab-link ${this.props.linkClassName} 
      ${this.props.isActive ? 'active' : ''}`}
        onClick={this.handleTabClick.bind(this)}>{this.props.linkClassName}</a>
      </li>
    )
  }
}

class Tabs extends React.Component {
  constructor(props, context) {
    super(props, context)
    this.state = {
      activeTabIndex: 0
    }
    this.handleTabClick = this.handleTabClick.bind(this)
  }

  handleTabClick(tabIndex) {
    this.setState({
      activeTabIndex: tabIndex === this.state.activeTabIndex ?
      this.props.defaultActiveTabIndex : tabIndex
    })
  }

  renderChild() {
    return React.Children.map(this.props.children, (child, index) => {
      return React.cloneElement(child, {
        onClick: this.handleTabClick,
        tabIndex: index,
        isActive: index === this.state.activeTabIndex
      })
    })
  }

  renderContent() {
    const { children } = this.props
    const { activeTabIndex } = this.state
    if (children[activeTabIndex]) {
      return children[activeTabIndex].props.children
    }
  }

  render() {
    return (
      <div>
        <ul>
          {this.renderChild()}
        </ul>
        <div className='tabcontent'>
          {this.renderContent()}
        </div>
      </div>
    )
  }
}

Tabs.defaultProps = {
  defaultActiveTabIndex: null
}

class Main extends React.Component {
  constructor(props) {
    super(props)

    this.state = {
      index: 1,
      disabledNext: false,
      disabledPrev: false
    }
  }

  togglePrev(e) {
    let index = this.state.index - 1;
    let disabledPrev = (index === 0);

    this.setState({ index: index, disabledPrev: disabledPrev, disabledNext: false })
  }

   toggleNext(e) {
     let index = this.state.index + 1;
     let disabledNext = index === (this.props.profiles.length - 1);

     this.setState({ index: index, disabledNext: disabledNext, disabledPrev: false })
   }
  render() {
   const { index, disabledNext, disabledPrev } = this.state
   const profile = this.props.profiles ? this.props.profiles[index] : null

   if (profile) {
     return (
       <div className='profile'>
          <Prev toggle={(e) => this.togglePrev(e)} active={disabledPrev} />
         <Next toggle={(e) => this.toggleNext(e)} active={disabledNext} />
          <Tabs>
            <Tab linkClassName={'Name'}><ProfileName {...profile} /></ Tab>
            <Tab linkClassName={'Number'}><ProfileCount {...profile} /></ Tab>
          </ Tabs>
       </div>
     )
   } else {
     return <span>error</span>
   }
  }
}

const App = () => (
  <div><Main profiles={profiles} /></div>
)

ReactDOM.render(
  <App />,
  document.getElementById('root')
)
ul {
    margin: 10px 0 0 0;
    padding: 0px;
    list-style: none;
    background: #6161a7;
}

li.tab { display: inline-block }

a {
    color: white;
    width: 60px;
    height: 30px;
    line-height: 30px;
    display: block;
    text-align: center;   
}

a.active { background: #969696 }

.tabcontent {
    padding: 20px;
    border: 1px solid;
}
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>

1 Ответ

0 голосов
/ 08 июня 2018

В главном компоненте у вас есть свойство "defaultActiveTabIndex", но вы никогда не распространяете его на дочерний компонент (вкладки).

Если вы распространяете его на компонент Tabs:

Основной компонент:

    render() {
    const {
      index,
      disabledNext,
      disabledPrev,
      defaultActiveTabIndex
    } = this.state;
    const profile = this.props.profiles ? this.props.profiles[index] : null;

    if (profile) {
      return (
        <div className="profile">
          <Prev toggle={e => this.togglePrev(e)} active={disabledPrev} />
          <Next toggle={e => this.toggleNext(e)} active={disabledNext} />
          <Tabs defaultActiveTabIndex={defaultActiveTabIndex}>
            <Tab linkClassName={"Name"}>
              <ProfileName {...profile} />
            </Tab>
            <Tab linkClassName={"Number"}>
              <ProfileCount {...profile} />
            </Tab>
          </Tabs>
        </div>
      );
    } else {
      return <span>error</span>;
    }
}

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

Компонент вкладок:

 componentWillReceiveProps(props) {
    const { defaultActiveTabIndex } = props;
    if (defaultActiveTabIndex !== this.state.activeTabIndex) {
      this.setState({ activeTabIndex: defaultActiveTabIndex });
    }
  }

Я также добавил изменение defaultActiveTabIndex внутри методов перехода prev и next (внутри MainComponent):

  togglePrev(e) {
    let index = this.state.index - 1;
    let disabledPrev = index === 0;

    this.setState({
      index: index,
      disabledPrev: disabledPrev,
      defaultActiveTabIndex: 0,
      disabledNext: false
    });
  }

  toggleNext(e) {
    let index = this.state.index + 1;
    let disabledNext = index === this.props.profiles.length - 1;

    this.setState({
      index: index,
      disabledNext: disabledNext,
      defaultActiveTabIndex: 0,
      disabledPrev: false
    });
  }

Этоне является неизбежным в вашем случае, но я поместил его там, так что вы знаете, что можете изменить его там - на случай, если вы хотите показать другую активную вкладку «по умолчанию» при предыдущей / следующей печати. ​​

Полная (рабочий) пример кода здесь: https://codesandbox.io/s/6x6mmr6vwk

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...