2

Я создаю навигацию по основным деталям, как пример здесь the react router example;React Router master-detail: дочерний компонент не отображает новый вид до обновления страницы

У меня есть компонент контейнера OneCheckpointContainer, который отображает навигационную панель CheckpointNav (в ссылки), и компонент данных OneCheckpointData (этого парня fetchs данных от нагрузки, и оказывает OneCheckpointView.

Когда я нажимаю один из ссылок в CheckpointNav ничего не происходит, за исключением того, что URL-адрес в браузере изменяется. Пока я не обновляю страницу, которую извлекают новые данные, а затем отображается новый компонент в детском представлении (также нет ошибок)

I я не уверен, что эта ошибка связана с тем, что дочерний компонент также отвечает за выборку данных, а также vie ш.

Вот как у меня есть настройки маршрутов:

<Route path="/modules/:id" component={OneCheckpointContainer}> 
    <Route path="/modules/:id/checkpoints/:cp_id" component={OneCheckpointData} /> 
    </Route> 

OneCheckpointContainer

import React from 'react'; 
import CheckpointNav from './CheckpointNav'; 

class OneCheckpointContainer extends React.Component { 
    constructor(props, context) { 
    super(props, context); 

    this.state = { 
     checkpoints: null, 
     user: null 
    }; 

    } 

    componentWillMount() { 
    this.loadCheckpoints(); 
    this.context.getUser((data) => this.setState({ user: data })); 
    } 

    loadCheckpoints() { 
    $.ajax({ 
     url: `/api/v1/modules/student/${this.props.params.id}/checkpoints`, 
     method: 'GET', 
    }).done((data) => { 
     this.setState({ checkpoints: data }); 
    }); 
    } 

    render() { 
    return (
     <div> 
     <div className="col-xs-3"> 
      <CheckpointNav mid={this.props.params.id} checkpoints={this.state.checkpoints} /> 
     </div> 
     <div className="col-xs-9"> 
      { this.props.children || <div>No Children Yet</div>} 
     </div> 
     </div> 
    ) 
    } 
} 

OneCheckpointContainer.displayName = OneCheckpointContainer; 

OneCheckpointContainer.contextTypes = { 
    getUser: React.PropTypes.func.isRequired 
}; 

export default OneCheckpointContainer; 

Вот CheckpointNav, хотя я не считаю, что ошибка находится здесь:

import React from 'react'; 
import NavLink from '../widgets/NavLink'; 

const CheckpointNav = (props) => { 
    const checkpointList = props.checkpoints && props.checkpoints.length > 0 ? 
    props.checkpoints.map((item) => { 
     return <li key={item.cp._id} className="list-group-item"> 
     <NavLink className="nav-link" to={"/modules/" + props.mid + "/checkpoints/" + item.cp._id}> 
     { item.cp.title}</NavLink></li> 
    }) : <div>No CPS</div>; 
    return (
    <div className="card one-module-card"> 
     <div className="card-block modules-card-body"> 
     <ul className="list-group tags-group"> 
      { checkpointList } 
      <li className="list-group-item new-cp"><NavLink className="" 
      to={'/post/checkpoint/' + props.mid} 
      > 
      New Checkpoint 
      </NavLink></li> 
     </ul> 
     </div> 
    </div> 
); 

}; 

export default CheckpointNav; 

OneCheckpointData не получать новые данные и сделать новый, если я обновить

import React from 'react'; 
import CheckpointView from './CheckpointView'; 

class OneCheckpointData extends React.Component { 
    constructor(props, context) { 
    super(props, context); 

    this.state = { 
     checkpoint: null, 
     user: null 
    }; 

    } 

    componentWillMount() { 
    this.loadCheckpoint(); 
    this.context.getUser((data) => this.setState({ user: data })); 
    } 

    loadCheckpoint() { 
    $.ajax({ 
     url: `/api/v1/modules/three/cp/${this.props.params.cp_id}`, 
     method: 'GET', 
    }).done((data) => { 
     this.setState({ checkpoint: data }); 
    }); 
    } 

    render() { 
    return this.state.checkpoint ? <CheckpointView user={this.state.user} checkpoint={this.state.checkpoint} /> : null; 
    } 
} 

OneCheckpointData.displayName = OneCheckpointData; 

OneCheckpointData.contextTypes = { 
    getUser: React.PropTypes.func.isRequired 
}; 

export default OneCheckpointData; 

** Я опустили OneCheckpointView, так как она должна быть irrelavant **

ответ

5

В, том случае, вы можете получить реквизит в качестве параметра loadCheckpoing(props) функции, и вы можете отправить новые реквизиты на componentWillReceiveProps так же, как ниже

componentWillMount(this.props) { 
    this.loadCheckpoint(this.props); 
} 

componentWillReceiveProps(nextprops) { 
    this.loadCheckpoint(nextprops); 
} 

loadCheckpoint(props) { 
    this.context.getUser((data) => this.setState({ user: data })); 
    $.ajax({ 
    url: `/api/v1/modules/three/cp/${props.params.cp_id}`, //please check i have replace the this.props to props as we have props as a parameter 
    method: 'GET', 
    }).done((data) => { 
    this.setState({ checkpoint: data }); 
    }); 
} 

я предпочтет использовать реагирующий redux или reflux для обработки вашего запроса данных ajax, но мое предлагаемое решение должно выполнить эту работу за вас.

+0

Я думаю, что понимаю, для чего вы собираетесь, но вы не можете передать this.props в качестве аргумента для компонентаWillMount – fresh5447

1

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

Для этого самым простым способом является добавление componentWillReceiveProps, который сравнивает предыдущие реквизиты с новым и при необходимости извлекает новые данные.

Альтернативный способ заключается в добавлении обработчика onEnter в конфигурацию ваших маршрутов для извлечения данных при каждом изменении маршрута.

Проверьте this question's answers, чтобы увидеть примеры обоих подходов.

1

Я думаю, это связано с тем, что вы вызывали функции loadcheckpoints в componentwillMount. Это вызывается только один раз в жизненном цикле компонента. Поскольку компонент уже смонтирован, когда вы нажали ссылку в навигационной панели, compoenntwillmount не будет вызываться. Если нет, выборка данных отсутствует.

Я думаю, вы должны попробовать следующий подход. Функция onclick ссылок в CheckpointNav должна быть передана из OneCheckpointContainer. Загруженные данные должны быть установлены в контейнер, который передает данные OneCheckpointData в качестве реквизита.

1

Два шага к диагностике:

  1. проверить ли ваш метод loadCheckpoint был вызван каждый раз, когда вы нажимаете другую ссылку. Просто оставьте одну строку, как console.log(new Date().toLocaleTimeString()) в этом методе

  2. если шаг 1 успешно, то проверьте, есть ли this ссылка вопрос в этой части: (data) => { this.setState({ checkpoint: data }); }

Кстати, вы бы лучше положить Аякса позвоните по телефону componentDidMount. См: https://facebook.github.io/react/docs/component-specs.html#mounting-componentdidmount