2016-03-30 6 views
1

У меня есть несколько маршрутов, но когда некоторые из них нажимаются, реакция не перерисовывает. Вот как мои маршруты выглядят:React-Router не перерисовывается, когда я нажимаю новую ссылку.

<Route path="/" component={App}> 
    <IndexRoute component={Home}/> 
    <Route path="/about" component={About}/> 
    <Route path="/chat" component={Chat}> 
     <Route path="/chat/:chat_room" component={Chat_Room}/> 
    </Route> 
    <Route path="/login" component={Login}/> 
    </Route> 

Вот мой /chat компонент:

export default React.createClass({ 
    loadChatRoomsFromServer: function() { 
    $.ajax({ 
     url: '/chat_rooms', 
     dataType: 'json', 
     cache: false, 
     success: function(data) { 
     this.setState(data); 
     }.bind(this), 
     error: function(xhr, status, err) { 
     console.error('/chat_rooms', status, err.toString()); 
     }.bind(this) 
    }); 
    }, 
    getInitialState: function(){ 
     return {chat_rooms: []}; 
    }, 
    componentDidMount: function() { 
     this.loadChatRoomsFromServer(); 
    }, 
    render: function() { 
    var chat_nav_links = this.state.chat_rooms.map(function(rooms, i){ 
     return (
      <div key={i}> 
       <li><NavLink to={"/chat/" + rooms.name}>{rooms.name}</NavLink></li> 
      </div> 
     ); 
    }); 
    return (
     <div> 
      {chat_nav_links} 
      {this.props.children} 
     </div> 
    ); 
    } 
}); 

и мой /chat_room компонент:

var ChatApp = React.createClass({ 

    getInitialState: function(){ 
     var chat_room = socket.subscribe(this.props.params.chat_room); 
     var chat_room_channel = this.props.params.chat_room; 
     chat_room.on('subscribeFail', function(err) { 
     console.log('Failed to subscribe to '+chat_room_channel+' channel due to error: ' + err); 
     }); 
     chat_room.watch(this.messageReceived); 
     return {messages: []}; 
    }, 
    messageReceived: function(data){ 
     var messages = this.state.messages; 
     var newMessages = messages.concat(data); 
     this.setState({messages: newMessages}); 
    }, 

    render: function() { 
    return (
     <div> 
      <h2>{this.props.params.chat_room}</h2> 
      <div className="container"> 
       <div className="messages"> 
       <MessagesList messages={this.state.messages}/> 
       </div> 
       <div className="actions"> 
       <ChatForm chat_room={this.props.params.chat_room}/> 
       </div> 
      </div> 
     </div> 
    ) 
    } 
}); 

К сожалению об огромном количестве кода, гряду от Angular to learn React, и я не совсем уверен, какие кодовые фрагменты еще актуальны. Так что медведь со мной.

Проблема, скажем, у меня есть 3 chat_rooms Волейбол, теннис, футбол. Если я сначала нажму на Soccer, все будет в порядке и отлично работает, но если я нажму на ссылку Теннис, клавиши реагирования не изменятся, и я буду говорить в канале Soccer.

Теперь я могу получить номер для изменения, но я должен пойти в /about, а затем вернуться назад и нажать на /chat/tennis, чтобы перейти от футбола к теннису.

Я бы очень хотел не использовать Redux/Flux для этого, поскольку я планирую перейти на MobX, я полагаю, что я не изменяю состояние правильно, поэтому он не обновляет dom, но я застрял на этом для через пару дней, и я не понимаю, что я делаю неправильно. Благодаря!

ответ

7

Компонент ChatRoom остается установленным, когда вы нажимаете на новую ссылку в чате: единственное, что здесь меняется, это идентификатор чата, который ваш компонент получает реквизит.

Чтобы заставить его работать, у вас есть только методы какой-либо компонента в течение жизненного цикла в компоненте Chatroom (подробнее о методах жизненного цикла компоненты here) настроек:

var ChatRoom = React.createClass({ 
    getInitialState: function() { // sets initial state only 
     return {messages: []}; 
    }, 

    componentDidMount: function() { // sets-up subscription after 1st rendering 
     this.subscribeToChatRoom(this.props.params.chat_room); 
    }, 

    componentWillReceiveProps: function(nextProps) { // when props change! 
     if (nextProps.params.chat_room !== this.props.params.chat_room) { 
      // reinits state for next rendering: 
      this.setState({messages: []}); 
      // cleans-up previous subscription: 
      this.unsubscribeToChatRoom(this.props.params.chat_room); 
      // sets-up new subscription: 
      this.subscribeToChatRoom(nextProps.params.chat_room); 
     } 
    }, 

    componentWillUnmount: function() { // performs some clean-up when leaving 
     this.unsubscribeToChatRoom(this.props.params.chat_room); 
    }, 

    subscribeToChatRoom: function(chatRoomId) { 
     var chat_room = socket.subscribe(chatRoomId); 
     chat_room.on('subscribeFail', function(err) { 
      console.log('Failed to subscribe to ' + chatRoomId 
       + ' channel due to error: ' + err); 
     }); 
     chat_room.watch(this.messageReceived); 
    }, 

    unsubscribeToChatRoom: function(chatRoomId) { 
     // socket un-subscription 
    }, 

    messageReceived: function(data) { 
     var messages = this.state.messages; 
     var newMessages = messages.concat(data); 
     this.setState({messages: newMessages}); 
    }, 

    render: function() { 
     return (
      <div> 
       <h2>{this.props.params.chat_room}</h2> 
       <div className="container"> 
        <div className="messages"> 
         <MessagesList messages={this.state.messages} /> 
        </div> 
        <div className="actions"> 
         <ChatForm chat_room={this.props.params.chat_room} /> 
        </div> 
       </div> 
      </div> 
     ) 
    } 
}); 
+0

Спасибо за отличную запись, я очень ценю это! Поэтому всякий раз, когда у меня есть ссылка, например '/ places /: my_place', я всегда должен проверять с помощью componentWillReceiveProps, потому что мой класс уже был создан один раз? Опять же, это был отличный ответ, мне придется погрузиться в крючки жизненного цикла. Благодаря! –

+1

Добро пожаловать! ;-) Вам нужно будет выполнить проверку с помощью компонента componentWillReceiveProps() только в том случае, если вы хотите обновить локальное состояние до нового рендеринга и/или если вам нужно выполнить какую-либо работу async (например, получение новых данных). –

+0

О, огромное спасибо! Я уверен, что скоро наткнутся на несколько асинхронных вызовов и буду снова задавать этот вопрос. Я вижу, что у вас всего 26 очков, вы должны публиковать здесь чаще, если только каждый дал столь же полный ответ, как и вы! –

0

Вы импортировали функцию observer с mobx-react? Чтобы компоненты стали включенными MobX, они должны быть объявлены следующим образом: var ChatApp = observer(React.createClass({ ...

+0

Нет у меня нет начал использовать MobX, но работал над выяснением реакции сначала, прежде чем я сделал его реактивным с MobX. Я просто пытаюсь понять, что происходит в первый раз. Есть ли способ заставить изменение состояния, когда я направляюсь к другой ссылке? Если нет, возможно, вы могли бы показать мне предпочтительный способ MobX изменить состояние на клике или даже на потоке. –