2016-09-17 3 views
0

저는 ReactJS를 배우고 있고 제 물건의 상태를 관리하는 데 몇 가지 문제가 있습니다. 나는 내가하고 싶은 일과 내가 취하는 접근법을 아래에서 설명했다.ReactJS에서 JSON 객체의 일부 속성 상태를 관리하는 방법은 무엇입니까?

일반 아이디어는 REST 서비스로부터 복잡한 JSON 객체를 받는다. 이 더 큰 JSON 객체의 속성 중 하나는 "예약"입니다. 언젠가 어떤 프로젝트에 대한 예약을 나타냅니다. 예약 개체에는 "프로젝트", "시간"(수정 됨) 및 "availableProjects"목록이 있습니다. 사용 가능한 프로젝트는 드롭 다운 방식으로 표시되며, 사용자는이를 선택하여 "reservation.project"속성을 업데이트 할 수 있습니다. 모든 예약, 시간 및 일부 다른 속성을 채운 후이 수정 된 개체를 다시 서버에 보내려고합니다. 여기

코드입니다 : 내가 입력 "시간"을 수정할 수 없습니다

var ReservationBox = React.createClass({ 
getInitialState: function() { 
    return { 
     reservation: this.props.reservation //IS THIS ANTI-PATTERN ? 
    } 
}, 
onSelectProject: function (selectedProject) { 
    this.setState({reservation: {project: selectedProject}}); // IT WORKS but I don't know I did it correctly according to best practices :-) 
}, 
handleHoursChange: function (e) { 
    this.setState({reservation: {hours: e.target.value}}) // THIS DOES NOT WORK 
}, 
render: function() { 
    return (
     <div> 
      {this.state.name} 
      <div className="btn-group timesheet-project-column"> 
       <button type="button" 
         className="btn btn-primary">{this.state.reservation.project.projectName}</button> 
       <button type="button" className="btn btn-primary dropdown-toggle" data-toggle="dropdown" 
         aria-haspopup="true" aria-expanded="false"> 
        <span className="caret"></span> 
        <span className="sr-only">Toggle Dropdown</span> 
       </button> 
       <AvailableProjectsListBox reservation={this.state.reservation} 
              onSelectProject={this.onSelectProject}/> 
      </div> 
      <div className="timesheet-column"> 
       <button type="button" className="btn btn-default"> 
        <span className="glyphicon glyphicon-pencil"/> 
       </button> 
      </div> 
      <div className="timesheet-column"> 
       <input type="text" className="form-control timesheet-hour" 
         value={this.state.reservation.hours} 
         onChange={this.handleHoursChange}/> 
      </div> 
      <div className="timesheet-column"> 
       <button type="button" className="btn btn-danger"> 
        <span className="glyphicon glyphicon-trash img-circle text-danger"></span> 
       </button> 
      </div> 
     </div> 
    ); 
} 
}); 


var AvailableProjectsListBox = React.createClass({ 
    render: function() { 
     var onSelectProject = this.props.onSelectProject; 
     var availableProjects = this.props.reservation.availableProjects.map(function (availableProject) { 
      return (
       <AvailableProject availableProject={availableProject}  
onSelectProject={onSelectProject}/> 
      ); 
     }); 
     return (
      <ul className="dropdown-menu"> 
       {availableProjects} 
      </ul> 
     ); 
    } 
}); 

var AvailableProject = React.createClass({ 
    handleSelectProject: function() { 
     this.props.onSelectProject(this.props.availableProject.project); 
    }, 
    render: function() { 
     return (
      <li><a href="#" onClick={this.handleSelectProject}> 
       {this.props.availableProject.project.projectName}</a> 
      </li> 
     ); 
    } 
}); 

- 그것은 초기 값을 보유하고 있습니다. 내 접근 방식에있어 잘못된 점은 무엇입니까? 어떻게 큰 JSON 개체가 많은 부분이 수정되지 않습니다 (그래서 내가 소품으로 중첩 된 구성 요소에 전달) 및 일부 속성의 상태를 수정해야 할이 상황을 처리 할 수 ​​있습니까?

EDIT : 이제 예상대로 작동하지만 JSON을 전달하는 JSON을 업데이트하는 것이 좋을 것이라고 생각합니다. 더 나은 방법이되어야하지만 마침내 내 상태 '프로젝트'와 '시간'을 동기화 상태로 유지합니다. JSON '예약'개체.

var ReservationBox = React.createClass({ 
    getInitialState: function() { 
     return { 
      projectName: this.props.reservation.project.projectName, 
      hours: this.props.reservation.hours 
     } 
    }, 
    onSelectProject: function (selectedProject) { 
     this.setState({projectName: selectedProject.projectName}); 
     this.props.reservation.project = selectedProject; 
    }, 
    handleHoursChange: function (e) { 
     this.setState({hours: e.target.value}) 
     this.props.reservation.hours = e.target.value; 
    }, 
    render: function() { 
     return (
      <div> 
       <div className="btn-group timesheet-project-column"> 
        <button type="button" 
          className="btn btn-primary">{this.state.projectName}</button> 
        <button type="button" className="btn btn-primary dropdown-toggle" data-toggle="dropdown" 
          aria-haspopup="true" aria-expanded="false"> 
         <span className="caret"></span> 
         <span className="sr-only">Toggle Dropdown</span> 
        </button> 
        <AvailableProjectsListBox reservation={this.props.reservation} 
               onSelectProject={this.onSelectProject}/> 
       </div> 
       <div className="timesheet-column"> 
        <button type="button" className="btn btn-default"> 
         <span className="glyphicon glyphicon-pencil"/> 
        </button> 
       </div> 
       <div className="timesheet-column"> 
        <input type="text" className="form-control timesheet-hour" 
          value={this.state.hours} 
          onChange={this.handleHoursChange}/> 
       </div> 
       <div className="timesheet-column"> 
        <button type="button" className="btn btn-danger"> 
         <span className="glyphicon glyphicon-trash img-circle text-danger"></span> 
        </button> 
       </div> 
      </div> 
     ); 
    } 
}); 
+0

* "이 기능이 작동하지 않습니다"*는 무엇을 의미합니까? 콘솔에 오류가 발생합니까 아니면 자동으로 실패합니까? – ivarni

+0

입력 필드 "input type ="text "className ="양식 컨트롤 시간표시 " value = {this.state.reservation.hours} onChange = {this.handleHoursChange} />"내가 지정한 기본값을 보유합니다. in getInitialState. 새 항목을 입력하면 기본적으로 즉시 덮어 씁니다. –

+0

데이터베이스의 시간을 업데이트 하시겠습니까? 아니면 로컬로 유지하고 싶습니까? – jacoballenwood

답변

0

당신은이 일을 "나쁜"방법입니다 올바른 위치 : 경험이 사람이 제대로 수행하는 방법 몇 가지 힌트 줘 반작용 있다면 감사하겠습니다.

React에서는 Props와 State를 절대로 직접 수정해서는 안됩니다. 그들은 불변으로 간주됩니다. 수 있습니다 그들을 직접 변경 (당신이 한 것처럼),하지만 그것을 방해하는 방법을 방해 Re-render 루프, 그리고 중 하나의 위험을 실행 1.해야 할 때 업데이 트하지 않거나 2. 부모 컴퍼넌트

그러나 React는 필요시 상태를 수정하는 데 필요한 도구를 제공합니다 (this.setState({}) 통해). 데이터를 직접 변경하는 대신 해당 방법을 사용하십시오.

이미 첫 번째 줄의 handleHoursChange 안에 있습니다. 두 번째 줄은 제거하면됩니다.

상위 구성 요소로 업스트림을 전달해야하는 경우 올바르게 수행하는 올바른 방법은 하위의 소품 중 하나로 함수를 전달하는 것입니다. 간단한 예제는 다음과 같습니다.

var ReservationBoxParent = React.createClass({ 
    handleChange: function(hours){ 
     //do something with hours here 
    }, 
    render: function(){ 
     return <ReservationBox onChange={this.handleChange} reservation={this.props.reservation}/>; 
    } 
}); 

var ReservationBox = React.createClass({ 
    getInitialState: function(){ 
     return {hours: this.props.reservation.hours} 
    }, 
    handleHoursChange: function(hours){ 
     this.setState({hours: hours}); 
     this.props.onChange({hours: hours}); 
    }, 

    render: function(){ 
     return <input type="text" 
          value={this.state.hours} 
          onChange={this.handleHoursChange}/> 
    } 
}); 
+0

답변을 주셔서 감사합니다. 이제는 상태 및 소품 구성 요소하지만 ReservationBox 구성 요소에서 시간 상태를 설정하면보기 (그것은 ReservationBox의 현재 상태를 반영)를 업데이트하고 나는 서버에서받은 전역 JSON 개체를 업데이트하고 싶습니다. 나는 그것을 서버에서 가져온 "저장소"로 취급하고 사용자가 수정할 수 있습니다. 사용자는 많은 수정을 할 수 있습니다. 그 중 하나는 시간을 설정하고 프로젝트를 선택하지만 수정할 수있는 많은 다른 입력이 있습니다. 이러한 수정 후 DB에서 업데이트하려면이 개체를 서버로 보내고 싶습니다. .. –

+0

반응 디버거에서 볼 수 있듯이 반응 구성 요소의 '상태'속성 만 업데이트되지만 현재 JSON obj도 업데이트하려고합니다 (이제는 소품을 업데이트하여 수행하지만 잘못되었습니다). 필자는 글로벌 스토어와 redux와 같은 라이브러리의 개념에 대해 읽었지 만 처음에는 순수한 반응으로 어떻게 작동하는지 이해하려고합니다. –

+0

'handleChange'함수에서 'this.props.reservation.hours = hours'를 업데이트하려면 ReservationBoxParent에서 무엇을해야합니까? –

관련 문제