2016-02-24 4 views
2

Я занимаюсь преобразованием одной страницы в своем веб-приложении, чтобы использовать реакцию, а не jQuery и Vanilla JS, но я зацикливаюсь на том, как подойти к ней из-за того, насколько незнакомы I am с реакцией.React - Как обновить состояние после запроса AJAX

В настоящее время на странице у меня есть таблица html со строками, которые относятся к таблице базы данных и другому столбцу со ссылками для редактирования и удаления строк.

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

На данный момент у меня есть это (я использую родовое имя компонента (ModelName) для данного примера, чтобы избежать путаницы от того, что это на самом деле называется.):

var ModelNames = React.createClass({ 

    getInitialState: function() { 
    return {model_names: this.props.model_names}; 
    }, 

    render: function() { 

    var rows = []; 

    this.props.model_names.forEach(function(model_name) { 
     rows.push(<ModelName model_name={model_name} key={model_name.id} />); 
    }); 

    return (

     <div className="row"> 
     <div className="col-md-12"> 
      <table className="table table-striped table-bordered table-hover"> 
      <thead> 
       <tr role="row" className="heading"> 
       <th>Property 1</th> 
       <th>Property 2</th> 
       <th className="text-center">Options</th> 
       </tr> 
      </thead> 
      <tbody>{rows}</tbody> 
      </table> 
     </div> 
     </div> 
    ); 
    } 
}); 

var ModelName = React.createClass({ 
    handleRemoveModelName: function() { 
    $.ajax({   
     url: '/model_name/ajax_delete', 
     data: { model_name_id: this.props.model_name.id }, 
     type: 'POST', 
     cache: false,   
     success: function(data) { 
     this.setState({ model_names: data }); // this is the part I am having trouble with 
     }.bind(this), 
     error: function() { 
     console.log('error');  
     }.bind(this) 
    }); 
    }, 
    render: function() { 
    return (
     <tr id={"model_name_" + this.props.model_name.id}> 
     <td>{this.props.model_name.property_1}</td> 
     <td>{this.props.model_name.property_2}</td> 
     <td className="text-center"> 
      <a href="javascript:;" className="btn btn-xs" onClick={this.handleEditModelName}><i className="fa fa-pencil"></i></a> <a href="javascript:;" className="btn btn-xs" onClick={this.handleRemoveModelName}><i className="fa fa-remove"></i></a> 
     </td> 
     </tr> 
    ); 
    } 
}); 

ReactDOM.render(
    // this comes from Rails 
    <ModelName model_names={<%= @model_names.to_json %>} />, 
    document.getElementById('react') 
); 

Удаление с помощью AJAX работает отлично и серверная сторона отвечает на все строки в таблице базы данных (после ее удаления), поэтому ответ json находится в точно таком же формате, как и исходные данные, представленные на загрузке страницы, я просто пытаюсь выяснить, как обновите состояние, чтобы команда реагировала на удаление только что удаленной записи.

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

Update

var ModelNames = React.createClass({ 
    handleRemoveModelName: function(id) { 
    $.ajax({   
     url: '/model_name/ajax_delete', 
     data: { model_name_id: id }, 
     type: 'POST', 
     cache: false,   
     success: function(data) { 
     this.setState({ model_names: data }); 
     }.bind(this), 
     error: function() { 
     console.log('error'); 
     }.bind(this) 
    }); 
    }, 

    render: function() { 
    var rows = []; 
    this.props.model_names.map(function(model_name) { 
     return (
     <ModelName 
      model_name={model_name} 
      key={model_name.id} 
      onRemove={this.handleRemoveModelName} 
     /> 
    ); 
    }, this); 

    // ... 
    } 
}); 

var ModelName = React.createClass({ 
    handleRemoveModelName: function() { 
    this.props.onRemove(this.props.model_name.id); 
    }, 
    // ... 
}); 

Кроме того, просто чтобы попробовать и включать все соответствующие, кнопка удаления все еще имеет onClick={this.handleRemoveModelName} для ModelNamereturn.

ответ

1

Вы должны решить, где должен быть источник истины для ваших данных. В вашей текущей настройке оно находится в ModelNames.

Вместо того, чтобы иметь ModelName, выполните удаление, позвольте ModelNames сделать это, так как он владеет данными.

Просто передайте обратный вызов ModelName, который вызывается при его удалении. В этом примере мы добавляем новое свойство к компоненту ребенка, onRemove который вызывается, когда кнопка удаления нажата:

var ModelNames = React.createClass({ 
    handleRemoveModelName: function(id) { 
    // make Ajax call here 
    }, 

    render: function() { 
    var rows = this.state.model_names.map(function(model_name) { 
     return (
     <ModelName 
      model_name={model_name} 
      key={model_name.id} 
      onRemove={this.handleRemoveModelName} 
     /> 
    ); 
    }, this); 

    // ... 
    } 
}); 

var ModelName = React.createClass({ 
    handleRemoveModelName: function() { 
    this.props.onRemove(this.props.model_name.id); 
    }, 
    // ... 
}); 

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

Это делает ModuleName компонентом «дампа». Он не имеет никакого отношения к управлению данными и передает только полученные данные.


Другой вопрос заключается в том, что вы читаете из реквизита в ModelNames (this.props.model_names), а не государство. Состояние и реквизит разные. Вы должны прочитать из состояния (this.state.model_names), чтобы компонент обновлялся при изменении состояния.

+0

Вау, спасибо за ответ Феликс - очень ценим. Теперь попробуем попробовать. – martincarlin87

+0

Uh. Я действительно запутался с именами компонентов. Я просто видел, что вы уже используете состояние в «ModelNames». Позвольте мне уточнить свой ответ. –

+0

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

3

Поверх ответ Феликса Клинг, вы должны были бы как-то общаться между ModalNames и ModalName для обновления состояния, так как государство управляется ModalNames и событие вызывается в ModalName.

Одно решение передать функцию, которая обновляет состояние на ModalName:

ModalNames:

var ModelNames = React.createClass({ 
    ... 
    updateState: function(modal_names) { 
    this.setState({modal_names}) 
    }, 
    render: function() { 
    var rows = []; 

    this.state.model_names.forEach(function(model_name) { 
     rows.push(<ModelName model_name={model_name} key={model_name.id} updateState={this.updateState} />); 
    }); 
    ... 
    } 
} 

ModalName:

var ModelName = React.createClass({ 
    handleRemoveModelName: function() { 
    $.ajax({   
     url: '/model_name/ajax_delete', 
     data: { model_name_id: this.props.model_name.id }, 
     type: 'POST', 
     cache: false,   
     success: function(data) { 
     this.props.updateState(data); 
     }.bind(this), 
     error: function() { 
     console.log('error');  
     }.bind(this) 
    }); 
    }, 
    ... 
} 

Альтернативное решение состоит в определении handleRemoveModelName в ModalNames, который принимает в id, вызывает ajax и делает setState, как вы изначально имели.

+0

благодарит Куджуру, я попробую. – martincarlin87

Смежные вопросы