01/10/2018, 10:31

Lấy dữ liệu state của component từ bên ngoài - React

Mình đang tìm hiểu React, mắc ở chỗ lấy dữ liệu của 1 component từ bên ngoài hoặc component khác.
Ví dụ:
(Copy từ Vim nên nó bị mấy dấu | các bạn đừng để ý nhé)

ComplieButton.jsx

class ComplieButton extends React.Component
{                              
  render()                                 
  {                                        
  ¦ return (                               
  ¦ ¦ <button                              
  ¦ ¦ ¦ className="myButton"            
  ¦ ¦ >                                    
  ¦ ¦ ¦ Complie                            
  ¦ ¦ </button>                            
  ¦ );                                     
  }                                        
}                                          

Editor.jsx

class Editor extends React.Component
{
  constructor(props)
  {
  ¦ super(props);

  ¦ this.state = {
  ¦ ¦ value: props.value,
  ¦ };
  }
                                               
  render()
  {
  ¦ return (
  ¦ ¦ <AceEditor
  ¦ ¦ ¦ onChange={this.onChange.bind(this)}
  ¦ ¦ ¦ value={this.state.value}
  ¦ ¦ />
  ¦ );
  } 
} 

Mình muốn là làm sao để lấy được giá trị của Editor.state.value từ component ButtonComplie

Hung viết 12:45 ngày 01/10/2018

Giả sử CompileButton ở Child Component của Editor.
B1: Tạo 1 method trong Editor, ví dụ compile(), chức năng thay đổi state.
B2: Truyền method vừa tạo vô CompileButton thông qua props: <CompileButton onButtonClick={this.compile.bind(this)} />
B3: Trong CompileButton, lúc render thêm props onClick={() -> this.props.onButtonClick()}

Dark.Hades viết 12:35 ngày 01/10/2018

Cảm ơn bạn, mình dùng cách này, lấy được dữ liệu và trao đổi cho các component được rồi, nhưng khi thay đổi state thì lại không thành công, nó vẫn giữ nguyên dữ liệu cũ.

Code dưới đây mình cho 2 Component đó làm Child cho Component App:
(Code hơi dài xíu)

class App extends React.Component                        
{                                                        
  constructor(props)                                     
  {                                                      
  ¦ super(props);                                        
                                                         
  ¦ this.state = {                                       
  ¦ ¦ editorValue: `#include <iostream>\n\nusing namespac
e std;\n\nint main (void)\n{\n  \n  return 0;\n}`,       
  ¦ };                                                   
                                                         
  ¦ this.onChangeEditor = this.onChangeEditor.bind(this);
  }                                                      
                                                         
  onChangeEditor(v, e)                                   
  {                                                      
  ¦ this.setState({                                      
  ¦ ¦ editorValue: v,                                    
  ¦ });                                                  
  ¦ console.log(this.state.editorValue);                 
  }                                                      
                                                         
  render()                                               
  {                                                      
  ¦ return (                                             
  ¦ ¦ <div>                                              
  ¦ ¦ ¦ <Editor                                          
  ¦ ¦ ¦ ¦ value={this.state.editorValue}                 
  ¦ ¦ ¦ ¦ onChange={this.onChangeEditor}                 
  ¦ ¦ ¦ />                                               
  ¦ ¦ ¦ <ComplieButton                                   
  ¦ ¦ ¦ ¦ editorValue={this.state.editorValue}           
  ¦ ¦ ¦ />                                               
  ¦ ¦ </div>                                             
  ¦ );                                                   
  }                                                      
}                                                        
class ComplieButton extends React.Component 
{                                           
  constructor(props)                        
  {                                         
  ¦ super(props);                           
                                            
  ¦ this.state = {                          
  ¦ ¦ editorValue: props.editorValue        
  ¦ };                                      
                                            
  ¦ this.onClick = this.onClick.bind(this); 
  }                                         
                                            
  onClick(e)                                
  {                                         
  ¦ console.log(this.state.editorValue);    
  }                                         
                                            
  render()                                  
  {                                         
  ¦ return (                                
  ¦ ¦ <button                               
  ¦ ¦ ¦ className="myButton"                
  ¦ ¦ ¦ onClick={this.onClick}              
  ¦ ¦ >                                     
  ¦ ¦ ¦ Complie                             
  ¦ ¦ </button>                             
  ¦ );                                      
  }                                         
}                                           
class Editor extends React.Component           
{                                              
  constructor(props)                           
  {                                            
  ¦ super(props);                              
                                               
  ¦ this.state = {                             
  ¦ ¦ value: props.value,                      
  ¦ ¦ onChange: props.onChange,                
  ¦ };                                         
  }                                            
                                               
  render()                                     
  {                                            
  ¦ return (                                   
  ¦ ¦ <AceEditor                                        
  ¦ ¦ ¦ onChange={this.state.onChange}         
  ¦ ¦ ¦ value={this.state.value}               
  ¦ ¦ />                                       
  ¦ );                                         
  }                                            
}                                              

Như code trên thì khi mình nhập dữ liệu vào trong Editor, log ở hàm onChangeEditor có cho ra nội dung đã thay đổi (tuy nhiên editor vẫn giữ nguyên nội dung), khi click vào ComplieButton thì dữ liệu của state editorValue vẫn như ban đầu

Hung viết 12:44 ngày 01/10/2018

Bạn bị duplicate state, 1 state ở App Component, 1state ở Editor Component. Hàm onChangeEditor() của bạn chỉ update state ở App Component, còn render ra UI lại thuộc state của Editor. Đó là lý do tại sao bạn code có update state nhưng UI hiển thị không thay đổi.

Giờ bạn xoá state ở Editor Component, sử dụng trực tiếp props thay vì state, code bạn ở Editor giống thế này:
<AppEditor ... value={this.props.value} />

Sau đó giống như mình đã viết, tạo compile() ở App Component, truyền compile xuống CompileButton, trong render() của CompileButton gọi callback onButtonClick() trong props.

Bạn có thể thay đổi tên cho dễ.

Dark.Hades viết 12:47 ngày 01/10/2018

Cảm ơn bạn, giờ mình hiểu chút ít về cấu trúc render của react rồi.

Ở bên ComplieButton mình dùng luôn this.props.editorValue là ok.

Bài liên quan
0