+3

Các vấn đề thường gặp trong ReactJS - P2

8 - Quên tạo các biến môi trường

Một số project phụ thuộc vào sự tồn tại của các biến môi trường để bắt đầu. Nếu bạn chạy các project này mà không cần các biến môi trường cần thiết thì chúng sẽ cố gắng sử dụng các giá trị không xác định cho chúng và có khả năng sẽ gây cho bạn một số lỗi khó hiểu.

Ví dụ, nếu một project kết nối với một cơ sở dữ liệu như MongoDB, rất có thể là nó sử dụng một biến môi trường như process.env.MONGO_URI để kết nối. Điều này cho phép project được sử dụng với các trường hợp MongoDB khác nhau trong các môi trường khác nhau.

Để chạy local project kết nối với một MongoDB, đầu tiên bạn phải export một biến môi trường MONGO_URI. Ví dụ, nếu bạn có một MongoDB local đang chạy trên cổng 27017, bạn sẽ cần phải làm điều này trước khi chạy project:

export MONGO_URI = "mongodb://localhost:27017/mydb"

Bạn có thể grep source project cho process.env để tìm ra những biến môi trường mà nó cần để hoạt động chính xác.

9 - Nhầm lẫn dấu ngoặc nhọn {} với dấu ngoặc đơn ()

Thay vì:

return {
  something();
};

Bạn cần:

return (
  something();
);

Cái đầu tiên sẽ cố gắng (và không) trả lại một đối tượng, trong khi cái thứ hai sẽ gọi hàm something() và trả lại giá trị mà hàm đó trả về.

Vì bất kỳ <tag> trong JSX sẽ dịch sang một lời gọi function, vấn đề này sẽ áp dụng khi trả về bất kỳ JSX nào.

Vấn đề này cũng phổ biến trong các cú pháp ngắn của các hàm của mũi tên.

Thay vì:

const Greeting = () => {
  <div>
    Hello World
  </div>
};

Bạn cần:

const Greeting = () => (
  <div>
    Hello World
  </div>
);

Khi bạn sử dụng dấu ngoặc nhọn với mũi tên function, bạn đang bắt đầu phạm vi chức năng đó. Cú pháp ngắn của các hàm mũi tên không sử dụng dấu ngoặc nhọn.

10 - Không bao bọc các đối tượng với dấu ngoặc đơn

Dấu ngoặc nhọn với ngoặc đơn ở trên cũng nhầm lẫn khi bạn muốn tạo một hàm mũi tên ngắn trả về một plain-old object. Thay vì:

const myAction = () => { type: 'DO_THIS' };

Bạn cần:

const myAction = () => ({ type: 'DO_THIS'});

Nếu không đóng gói đối tượng trong dấu ngoặc, bạn sẽ không sử dụng cú pháp ngắn. Bạn sẽ thực sự đang định nghĩa một label cho một chuỗi! Điều này là phổ biến bên trong các updater function của method setState vì nó cần phải trả lại một đối tượng. Bạn cần phải bọc đối tượng đó bằng dấu ngoặc đơn nếu bạn muốn sử dụng cú pháp function mũi tên ngắn. Thay vì:

this.setState(prevState => { answer: 42 });

Bạn cần:

this.setState(prevState => ({ answer: 42 }));

11 - Không sử dụng đúng phần viết hoa của các elements và props API

Đó là React.Component, không phải React.component. Đó là componentDidMount chứ không phải ComponentDidMount. Đó thường là ReactDOM chứ không phải ReactDom.

Chú ý đến cách viết hoa API mà bạn cần. Nếu bạn sử dụng viết hoa không chính xác, lỗi bạn sẽ gặp phải có thể không nêu rõ vấn đề là gì.

Khi import từ reactreact-dom, đảm bảo rằng bạn đang nhập đúng tên và những gì bạn đang sử dụng hoàn toàn giống với những gì bạn đang nhập. ESLint có thể giúp bạn chỉ ra những gì không được sử dụng.

Vấn đề này cũng phổ biến trong việc truy cập các props của component:

<Greeting userName="Max" />
// Inside the component, you need
props.userName

Nếu, thay vì props.userName, bạn sử dụng không chính xác props.username hoặc props.UserName, bạn sẽ sử dụng một giá trị không xác định. Lưu ý rằng, hoặc tốt hơn nữa, hãy làm cấu hình ESLint của bạn chỉ những vấn đề này ra là được.

12- Nhầm lẫn state object với instance properties

Trong một class component, bạn có thể định nghĩa một state object cục bộ và sau đó truy cập nó với this:

class Greeting extends React.Component {
  state = {
    name: "World",
  };
  render() {
    return `Hello ${this.state.name}`;
  }
}

Trên đây sẽ cho ra "Hello World". Bạn cũng có thể định nghĩa các instant properties cục bộ bên cạnh state:

class Greeting extends React.Component {
  user = {
    name: "World",
  };
  render() {
    return `Hello ${this.user.name}`;
  }
}

Trên đây cũng sẽ cho ra "Hello World".

state instance property là một cái đặc biệt vì React sẽ quản lý nó. Bạn chỉ có thể thay đổi nó thông qua setState và React sẽ phản ứng khi bạn làm. Tuy nhiên, tất cả các thuộc tính khác mà bạn định nghĩa sẽ không ảnh hưởng đến thuật toán dựng hình. Bạn có thể thay đổi this.user trong ví dụ trên theo ý mình và React sẽ không kích hoạt một chu kỳ render trong React.

13 - Nhầm lẫn <tag /> với </ tag>

Không đặt sai ký tự / trong các thẻ đóng của bạn. Phải thừa nhận rằng, đôi khi bạn có thể sử dụng <tag /> và những lần khác bạn cần </ tag>

Trong HTML, có một cái gì đó được gọi là "thẻ tự đóng" (AKA void tag). Đó là các thẻ đại diện cho các phần tử không có nút con. Ví dụ: thẻ img là một thẻ tự đóng:

<img src="..." />
// You don't use <img></img>

Thẻ div có thể có con và vì vậy bạn sử dụng các thẻ mở và đóng:

<div>
  // Children here...
</div>

Tương tự áp dụng cho các React components. Nếu componenet có nội dung con, nó có thể trông như thế này:

<Greeting>Hello!</Greeting>
// Notice the position of the / character.

Nếu component không có con, bạn có thể viết nó bằng các thẻ mở/đóng hoặc chỉ là một thẻ tự đóng:

// 2 valid ways
<Greeting></Greeting>
<Greeting />

Cách sử dụng dưới đây là không đúng:

// Wrong
<Greeting><Greeting />

Nếu bạn sai ký tự /, bạn sẽ nhận được lỗi như:

Syntax error: Unterminated JSX contents

14 - Giả sử import/export sẽ làm việc

Tính năng import/export là một tính năng chính thức của JavaScript (từ năm 2015). Tuy nhiên, đây là tính năng ES2015 duy nhất chưa được hỗ trợ đầy đủ trong các trình duyệt hiện đại và Node mới nhất.

Cấu hình phổ biến của project React là sử dụng WebpackBabel. Cả hai đều cho phép sử dụng tính năng này và biên dịch nó xuống một cái gì đó tất cả các trình duyệt có thể hiểu được. Bạn chỉ có thể sử dụng import/export nếu bạn có một cái gì đó như Webpack hoặc Babel trong luồng của bạn.

Tuy nhiên, khi import/export trong ứng dụng React bundled của bạn không có nghĩa là bạn chỉ có thể sử dụng chúng ở nơi nào bạn muốn! Ví dụ: nếu bạn đang làm hiển thị server-side thông qua Node mới nhất, mọi thứ sẽ không hoạt động cho bạn. Bạn rất có thể sẽ nhận được lỗi "không báo trước".

Để có Node hiểu import / export (bạn cần nếu bạn sử dụng chúng ở front-end và bạn cũng muốn thực hiện SSR), bạn sẽ phải chạy Node với một giá trị đặt sẵn Babel (như cài đặt sẵn env ) có thể chuyển đổi chúng. Bạn có thể sử dụng các công cụ như pm2, nodemon, và babel-watch để làm như vậy trong quá trình phát triển và Node khởi động lại mỗi khi bạn thay đổi một thứ.

15 - Không binding các methods xử lý

Tôi đã lưu cái này ở cuối vì đó là một vấn đề lớn và rất phổ biến.

Bạn có thể định nghĩa các class methods trong một component React và sau đó sử dụng chúng trong method render của component. Ví dụ:

class Greeting extends React.Component {
  whoIsThis() {
    console.dir(this); // "this" is the caller of whoIsThis
    return "World";
  }
  render() {
    return `Hello ${this.whoIsThis()}`;
  }
}
ReactDOM.render(<Greeting />, mountNode);

Tôi đã sử dụng method whoIsThis trong method render với this.whoIsThis do bên trong render, từ khóa this đề cập đến component instance gắn với phần tử DOM đại diện cho component.

React đảm bảo rằng "this" bên trong các method class của nó đề cập đến instance. Tuy nhiên, JavaScript không bind các instance tự động khi bạn sử dụng một tham chiếu đến method whoIsThis.

Dòng console.dir trong whoIsThis sẽ báo cáo một cách chính xác instance của component vì method đó được gọi trực tiếp từ method render với lời gọi rõ ràng (this). Bạn sẽ thấy object Greeting trong console khi bạn execute code ở trên:

Tuy nhiên, khi bạn sử dụng cùng một method trong một kênh delayed-execution, chẳng hạn như một event handler, người gọi sẽ không còn được rõ ràng và dòng lệnh console.dir sẽ không báo cáo instance component.

Xem code và output (sau khi click) dưới đây:

Trong đoạn code ở trên, React sẽ gọi method whoIsThis khi bạn nhấp vào chuỗi, nhưng nó sẽ không cho phép bạn truy cập vào instance của component bên trong nó. Đây là lý do tại sao bạn không xác định khi nhấp vào chuỗi. Đây là một vấn đề nếu method class của bạn cần truy cập vào những thứ như this.propsthis.state. Nó đơn giản sẽ không hoạt động.

Có nhiều giải pháp cho vấn đề này. Bạn có thể gom các method trong một inline function hoặc sử dụng lời gọi .bind để buộc các method để nhớ lời gọi của nó. Cả hai đều ổn cho các component cập nhật không thường xuyên. Bạn cũng có thể tối ưu hóa method bind bằng cách làm nó trong constructor của class thay vì trong method render. Tuy nhiên, giải pháp tốt nhất cho method này là cho phép các class-fields ECMAScript (vẫn là giai đoạn 3) thông qua Babel và chỉ sử dụng một hàm mũi tên cho các handler:

class Greeting extends React.Component {
  whoIsThis = () => {
    console.dir(this);
  }
  render() {
    return (
     <div onClick={this.whoIsThis}>
        Hello World
      </div>
    );
  }
}

Cái này sẽ hoạt động như mong đợi:


Đó là tất cả những gì mình có thể chia sẻ với mọi người ở thời điểm hiện tại. Cảm ơn mọi người vì đã đọc bài viết của mình.

Refer link: ReactJs - Medium forum


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí