2014-05-06 40 views
10

Tôi đang cố tạo/thử nghiệm một tiện ích có bộ lọc tìm kiếm và 2 bảng có mối quan hệ khóa-giá trị/cha-con. Bảng điều khiển bên phải chứa các danh mục, bảng điều khiển bên trái có các sở thích được liên kết với một danh mục riêng lẻ. Các hàng danh mục có thể chọn để hiển thị các hộp kiểm quan tâm liên quan. Tôi đã không nhận được đến điểm cố gắng để hiểu làm thế nào để cập nhật các hình thức nộp với các hộp kiểm tra, đầu tiên tôi cần phải hiểu thêm về cách chính xác để làm cho dòng dữ liệu.Làm cách nào để xử lý các sự kiện nhấp chuột trên các thành phần con trong React.js, có cách phản ứng "" không?

Đây là lần đột phá đầu tiên của tôi vào React và tôi biết rằng React khuyến khích luồng dữ liệu một chiều. Tôi cảm thấy rằng tôi đang cập nhật bảng điều khiển sở thích không chính xác bằng cách sử dụng jQuery để xử lý các sự kiện. Tôi muốn biết một số cách khác để cập nhật bảng điều khiển sở thích.

Từ những gì tôi đã đọc, để cập nhật phụ huynh (Tôi tin rằng nó được gọi là chủ sở hữu trong các tài liệu React) bạn cần xác định callbacks trên các thành phần con/sở hữu. Tôi đánh giá cao một lời giải thích về điều này và cũng có thể nếu tôi sử dụng sai quyền lợi trong tiểu bang so với đạo cụ. Tôi đã cố gắng chỉ có bộ lọc Tìm kiếm & các hộp kiểm là một phần của tiểu bang cho tiện ích con, bởi vì tôi đọc dữ liệu có thể lọc nên thuộc về đạo cụ.

CẬP NHẬT: Tôi đã thay đổi sở thích được khởi tạo trong getDefaultProps, vì vậy bây giờ tôi đang sử dụng chúng làm đạo cụ. Tôi nghĩ rằng đây là cách phản ứng, tôi có đúng không? Tôi cũng đã thay đổi cách mà các sở thích được cập nhật bằng cách thay đổi hàm handleCategoryRowClick. Tôi nghĩ rằng tôi đang làm mọi thứ theo cách phản ứng nhiều hơn bây giờ, nhưng vẫn sẽ yêu bất kỳ lời khuyên nào mà bất cứ ai có nhiều kinh nghiệm sử dụng React có thể cho, cảm ơn bạn.

Bất kỳ trợ giúp nào sẽ được đánh giá rất nhiều!

/** @jsx React.DOM */ 

var InterestRow = React.createClass({ 
    render: function() { 
     return (
      <div> 
       <label>{this.props.interest.name}</label> 
       <input type="checkbox" ref={this.props.key} value={this.props.key} /> 
      </div> 
     ) 
    } 
}); 

var InterestPanel = React.createClass({ 
    var interestPanel = this; 
    var rows = []; 

    render: function() { 
     var rows = []; 
     var i = 0; 

     _(this.props.interests).each(function (interest) { 
      rows.push(<InterestRow interest={interest} key={interest.value} />); 
     }); 

     return (
      <form>{rows}</form> 
     ) 
    } 
}); 

var CategoryRow = React.createClass({ 
    render: function() { 
     return (
      <li onClick={this.props.handleClick.bind(null, this.props.interests)}>{this.props.category}</li> 
     ) 
    } 
}); 

var CategoriesPanel = React.createClass({ 
render: function() { 
    var categoriesPanel = this; 
    var rows = []; 
    var categories = []; 
    var interests = []; 
    var interestSet = []; 
    var missedSet = []; 
    var lastCategory = null; 
    var category; 
    var interest; 
    var i = 0; 

    _.each(categoriesPanel.props.data, function (datum) { 
     name = datum.name; 
     value = datum.targeting_value; 
     category = name.split('/')[0]; 
     interest = {name: name.split('/')[1], value: value} 

     if (_.contains(interest.name.toLowerCase(), categoriesPanel.props.searchText.toLowerCase())) { 
      if (category !== lastCategory) { 
       if (interestSet.length > 0) { 
        interests.push(interestSet.concat(missedSet)); 
       } 

       lastCategory = category; 
       categories.push(category); 
       interestSet = []; 
       interestSet.push(interest); 
       missedSet = []; 
      } else { 
       if (!_.contains(categories, category)) { 
        categories.push(category); 
        interestSet.push(interest); 
       } else { 
        interestSet.push(interest); 
       } 
      } 
     } else { 
      if (category !== lastCategory) { 
       if (interestSet.length > 0) { 
        interests.push(interestSet.concat(missedSet)); 
       } 

       lastCategory = category; 
       interestSet = []; 
       missedSet = []; 
       missedSet.push(interest); 
      } else { 
       missedSet.push(interest); 
      } 
     } 
    }); 

    if (interestSet.length > 0) { 
     interests.push(interestSet.concat(missedSet)); 
    } 

    var interestsObject = _.zipObject(categories, interests); 

    _.each(interestsObject, function (interestSet, category) { 
     i++; 
     rows.push(<CategoryRow category={category} key={i} interests={interestSet} handleClick={categoriesPanel.props.handleClick} />) 
    }); 

    return (
     <div> 
      <ul>{rows}</ul> 
     </div> 
    ) 
} 
}); 

var SearchBar = React.createClass({ 
    handleChange: function() { 
     this.props.onUserInput(
      this.refs.searchTextInput.getDOMNode().value 
     ) 
    }, 
    render: function() { 
     return (
      <form onSubmit={this.handleSubmit}> 
       <input 
        type="text" 
        placeholder="Search Interests..." 
        value={this.props.searchText} 
        ref="searchTextInput" 
        onChange={this.handleChange} 
       /> 
      </form> 
     ); 
    } 
}); 

var InterestsTable = React.createClass({ 
loadDataFromTwitter: function() { 
    $.ajax({ 
     url: this.props.url, 
     dataType: 'json', 
     success: function(data) { 
      this.setProps({data: data}); 
     }.bind(this) 
    }); 
}, 
getInitialState: function() { 
    return { 
     searchText: '' 
    } 
}, 
getDefaultProps: function() { 
    return { 
     data: [], 
     interests: [] 
    } 
}, 
componentWillMount: function() { 
    this.loadDataFromTwitter(); 
}, 
handleUserInput: function(searchText) { 
    this.setState({ 
     searchText: searchText 
    }); 
}, 
handleCategoryRowClick: function(interests) { 
    this.setProps({ 
     interests: interests 
    }); 
}, 
render: function() { 
    return (
     <div> 
      <SearchBar 
       searchText={this.state.searchText} 
       onUserInput={this.handleUserInput} 
      /> 
      <CategoriesPanel 
       data={this.props.data} 
       searchText={this.state.searchText} 
       handleClick={this.handleCategoryRowClick} 
      /> 
      <InterestsPanel 
       interests={this.props.interests} 
       searchText={this.state.searchText} 
      /> 
     </div> 
    ); 
} 
}); 

React.renderComponent(
    <InterestsTable url="/api/interests" />, 
    document.getElementById('content') 
); 

Trả lời

9
  • Có một số kéo dài jQuery có thể được loại bỏ:
componentDidMount: function() { 
     $(document).on("handleCategoryRowClick", this.handleCategoryRowClick); 
    }, 
  • Treat props như bất di bất dịch như thường xuyên càng tốt và Phản ứng cuộc sống phương pháp chu kỳ sẽ làm việc như mong đợi. Trong trường hợp này, interests phải là state thay vì props vì thành phần InterestsTable sở hữu và sửa đổi nó; nó không được thông qua trong bởi cha mẹ của thành phần:
getInitialState: function() { 
     return { 
     interests: [], 
     searchText: "" 
     }; 
    }, 
    handleCategoryRowClick: function(e, interests) { 
     this.setState({ 
     interests: interests 
     }); 
    }, 
+0

Tôi quên để loại bỏ các chức năng jQuery, nhưng mã của tôi không còn có nó ... Từ Phản ứng docs [ở đây] (http: //facebook.github .io/reaction/docs/thinking-in-react.html # bước-4-xác định-nơi-bạn-tiểu-nên-sống của bạn) có vẻ như khuyến khích sử dụng các đạo cụ cho bất kỳ dữ liệu nào có thể được tính thông qua tiểu bang hoặc đạo cụ khác. Có lợi ích gì khi sử dụng đạo cụ so với nhà nước? Cách tôi hiện có thiết lập như đạo cụ và chức năng đang hoạt động. – evkline

+0

Tôi cập nhật mã của tôi, ssorallen ... Điều này có vẻ "Phản ứng-ish" với bạn? Ngoài ra, hiện tại bộ lọc tìm kiếm cập nhật các đầu vào hộp kiểm trên DOM. Nếu hộp kiểm được chọn và sau đó bộ lọc tìm kiếm cập nhật DOM, làm thế nào tôi có thể lưu trữ giá trị của hộp kiểm đã chọn trong React? Tôi có phải sử dụng jQuery để lấy và lưu trữ dữ liệu đó trên máy khách trước khi gửi nó đến máy chủ không? – evkline

+0

P.S. Tôi biết mã CategoriesPanel cần một số tái cấu trúc, tôi sẽ cấu trúc lại nó chỉ muốn mọi thứ hoạt động trước. Cảm ơn một lần nữa vì sự giúp đỡ. – evkline

Các vấn đề liên quan