HomeLập trìnhJavaScriptCác kỹ năng...

Các kỹ năng JavaScript bạn cần để phản ứng (+ Ví dụ thực tế)


Một trong những điều quan trọng nhất để hiểu về React là về cơ bản nó là JavaScript. Điều này có nghĩa là bạn càng giỏi JavaScript thì bạn càng thành công với React.

Hãy chia nhỏ 7 khái niệm cơ bản mà bạn nên biết về JavaScript để thành thạo React.

Và khi tôi nói những khái niệm này là cần thiết, ý tôi là chúng được sử dụng trong mọi ứng dụng mà nhà phát triển React tạo ra, không có ngoại lệ.

Học những khái niệm này là một trong những điều có giá trị nhất bạn có thể làm để tăng tốc khả năng tạo dự án React và trở thành nhà phát triển React lành nghề, vì vậy hãy bắt đầu nào.

Muốn bản sao của riêng bạn của hướng dẫn này?

Tải xuống cheatsheet ở định dạng PDF tại đây (mất 5 giây).

1. Khai báo hàm và hàm mũi tên

Cơ sở của bất kỳ ứng dụng React nào là thành phần. Trong React, các thành phần được xác định bằng cả hàm và lớp JavaScript.

Nhưng không giống như các hàm JavaScript, các thành phần React trả về các phần tử JSX được sử dụng để cấu trúc giao diện ứng dụng của chúng ta.

// JavaScript function: returns any valid JavaScript type
function javascriptFunction() {
  return "Hello world";
}

// React function component: returns JSX
function ReactComponent(props) {
  return <h1>{props.content}</h1>   
}

Lưu ý cách viết hoa khác nhau giữa tên của các hàm JavaScript và các thành phần của hàm React. Các hàm JavaScript được đặt tên theo cách viết hoa lạc đà, trong khi các thành phần của hàm React được viết bằng cách viết hoa pascal (trong đó tất cả các từ đều được viết hoa).

Có hai cách khác nhau để viết một hàm trong JavaScript: cách truyền thống, sử dụng function từ khóa, được gọi là một khai báo hàmvà như một chức năng mũi tênđược giới thiệu trong ES6.

Cả khai báo hàm và hàm mũi tên đều có thể được sử dụng để viết các thành phần hàm trong React.

Lợi ích chính của các hàm mũi tên là tính ngắn gọn của chúng. Chúng ta có thể sử dụng một số cách viết tắt để viết các hàm của mình nhằm loại bỏ các bản soạn sẵn không cần thiết, sao cho chúng ta thậm chí có thể viết tất cả trên một dòng.

// Function declaration syntax
function MyComponent(props) {
  return <div>{props.content}</div>;
}
 
// Arrow function syntax
const MyComponent = (props) => {
  return <div>{props.content}</div>;
}
 
// Arrow function syntax (shorthand)
const MyComponent = props => <div>{props.content}</div>;

/* 
In the last example we are using several shorthands that arrow functions allow:

1. No parentheses around a single parameter
2. Implicit return (as compared to using the "return" keyword)
3. No curly braces for function body
*/

Một lợi ích nhỏ của việc sử dụng các khai báo hàm trên các hàm mũi tên là bạn không phải lo lắng về các vấn đề với cẩu.

Do hành vi nâng của JavaScript, bạn có thể sử dụng nhiều thành phần hàm được tạo bằng khai báo hàm trong một tệp theo bất kỳ thứ tự nào bạn muốn.

Tuy nhiên, các thành phần chức năng được tạo bằng các chức năng mũi tên không thể được sắp xếp theo bất kỳ cách nào bạn muốn. Vì các biến JavaScript được nâng lên, các thành phần của hàm mũi tên phải được khai báo trước khi chúng được sử dụng:

function App() {
  return (
    <>
      {/* Valid! FunctionDeclaration is hoisted */}
      <FunctionDeclaration />
      {/* Invalid! ArrowFunction is NOT hoisted. Therefore, it must be declared before it is used */}
      <ArrowFunction />
    </>
}
  
function FunctionDeclaration() {
  return <div>Hello React!</div>;   
}

function ArrowFunction() {
  return <div>Hello React, again!</div>;   
}  

Một điểm khác biệt nhỏ khác trong việc sử dụng cú pháp khai báo hàm là bạn có thể xuất ngay một thành phần từ một tệp bằng cách sử dụng export default hoặc export trước khi hàm được khai báo. Bạn chỉ có thể sử dụng export từ khóa trước các chức năng mũi tên (xuất khẩu mặc định phải được đặt trên một dòng bên dưới thành phần).

// Function declaration syntax can be immediately exported with export default or export
export default function App() {
  return <div>Hello React</div>;   
}

// Arrow function syntax must use export only
export const App = () => {
  return <div>Hello React</div>;     
}

2. Chữ mẫu

JavaScript có một lịch sử vụng về khi làm việc với các chuỗi, đặc biệt nếu bạn muốn nối liền hoặc kết nối nhiều chuỗi với nhau. Trước khi có ES6, để cộng các chuỗi lại với nhau, bạn cần sử dụng + toán tử để thêm từng đoạn chuỗi với nhau.

Với việc bổ sung ES6, chúng tôi đã cung cấp một dạng chuỗi mới hơn được gọi là mẫu chữbao gồm hai dấu tích phía sau `` thay vì dấu nháy đơn hoặc kép.

Thay vì phải sử dụng + toán tử, chúng ta có thể kết nối các chuỗi bằng cách đặt một biểu thức JavaScript (chẳng hạn như một biến) trong một giá trị đặc biệt ${} cú pháp:

/* 
Concatenating strings prior to ES6.
Notice the awkward space after the word Hello?
*/
function sayHello(text) {
  return 'Hello ' + text + '!';
}

sayHello('React'); // Hello React!
 
/* 
Concatenating strings using template literals.
See how much more readable and predictable this code is?
*/
function sayHelloAgain(text) {
  return `Hello again, ${text}!`;
}

sayHelloAgain('React'); // Hello again, React!

Điểm mạnh của các mẫu chữ là khả năng sử dụng bất kỳ biểu thức JavaScript nào (nghĩa là bất kỳ thứ gì trong JavaScript phân giải thành một giá trị) trong ${} cú pháp.

Đọc thêm  Aprende JavaScript - Curso Completeo Desde Cero

Chúng ta thậm chí có thể bao gồm logic có điều kiện bằng cách sử dụng toán tử bậc ba, đây là cách hoàn hảo để thêm hoặc xóa một cách có điều kiện một quy tắc lớp hoặc kiểu cho một phần tử JSX nhất định:

/* Go to react.new and paste this code in to see it work! */
import React from "react";

function App() {
  const [isRedColor, setRedColor] = React.useState(false);

  const toggleColor = () => setRedColor((prev) => !prev);

  return (
    <button
      onClick={toggleColor}
      style={{
        background: isRedColor ? "red" : "black",
        color: 'white'
      }}
    >
      Button is {isRedColor ? "red" : "not red"}
    </button>
  );
}

export default App;

Nói tóm lại, các mẫu chữ rất tuyệt vời cho React bất cứ khi nào chúng ta cần tạo các chuỗi một cách linh hoạt. Ví dụ: khi chúng tôi sử dụng các giá trị chuỗi có thể thay đổi trong phần đầu hoặc phần thân trong trang web của mình:

import React from 'react';
import Head from './Head';

function Layout(props) {
  // Shows site name (i.e. Reed Barger) at end of page title
  const title = `${props.title} | Reed Barger`;  
    
  return (
     <>
       <Head>
         <title>{title}</title>
       </Head>
       <main>
        {props.children}
       </main>
     </>
  );
}

3. Câu điều kiện ngắn: &&, ||, Toán tử ba ngôi

Xét rằng React chỉ là JavaScript, rất dễ dàng để hiển thị (hoặc ẩn) các phần tử JSX một cách có điều kiện bằng cách sử dụng các câu lệnh if đơn giản và đôi khi là các câu lệnh switch.

import React from "react";

function App() {
  const isLoggedIn = true;

  if (isLoggedIn) {
    // Shows: Welcome back!
    return <div>Welcome back!</div>;
  }

  return <div>Who are you?</div>;
}

export default App;

Với sự trợ giúp của một số toán tử JavaScript cần thiết, chúng tôi giảm bớt sự lặp lại và làm cho mã của chúng tôi ngắn gọn hơn.

Chúng ta có thể chuyển đổi câu lệnh if ở trên thành câu lệnh sau, sử dụng nhà điều hành bậc ba. Toán tử bậc ba hoạt động chính xác giống như câu lệnh if, nhưng nó ngắn hơn, nó là một biểu thức (không phải câu lệnh) và có thể được chèn vào bên trong JSX:

import React from "react";

function App() {
  const isLoggedIn = true;

  // Shows: Welcome back!
  return isLoggedIn ? <div>Welcome back!</div> : <div>Who are you?</div>
}

export default App;

Các toán tử bậc ba cũng có thể được sử dụng bên trong dấu ngoặc nhọn (một lần nữa, vì nó là một biểu thức):

import React from "react";

function App() {
  const isLoggedIn = true;

  // Shows: Welcome back!
  return <div>{isLoggedIn ? "Welcome back!" : "Who are you?"</div>;
}

export default App;

Nếu chúng ta thay đổi ví dụ trên và chỉ muốn hiển thị văn bản nếu người dùng đã đăng nhập (nếu isLoggedIn là đúng), đây sẽ là một trường hợp sử dụng tuyệt vời cho && (và) nhà điều hành.

Nếu giá trị đầu tiên (toán hạng) trong điều kiện là đúng, thì && toán tử hiển thị toán hạng thứ hai. Nếu không, nó trả về toán hạng đầu tiên. Và vì nó là giả dối (là một giá trị được tự động chuyển đổi thành boolean false bởi JavaScript), nó không được hiển thị bởi JSX:

import React from "react";

function App() {
  const isLoggedIn = true;

  // If true: Welcome back!, if false: nothing
  return <div>{isLoggedIn && "Welcome back!"}</div>;
}

export default App;

Giả sử rằng chúng ta muốn làm ngược lại những gì chúng ta đang làm bây giờ: chỉ nói “Bạn là ai?” nếu isLoggedIn là sai. Nếu đó là sự thật, chúng tôi sẽ không hiển thị bất cứ điều gì.

Đối với logic này, chúng ta có thể sử dụng || (hoặc) toán tử. Về cơ bản nó hoạt động ngược lại với && nhà điều hành. Nếu toán hạng đầu tiên là true, thì toán hạng đầu tiên (falsy) được trả về. Nếu toán hạng đầu tiên là sai, toán hạng thứ hai được trả về.

import React from "react";

function App() {
  const isLoggedIn = true;

  // If true: nothing, if false: Who are you?
  return <div>{isLoggedIn || "Who are you?"}</div>;
}

export default App;

4. Ba phương thức mảng: .map(), .filter(), .reduce()

Việc chèn các giá trị nguyên thủy vào các phần tử JSX rất dễ dàng – chỉ cần sử dụng dấu ngoặc nhọn.

Chúng ta có thể chèn bất kỳ biểu thức hợp lệ nào, bao gồm các biến chứa giá trị nguyên thủy (chuỗi, số, boolean, v.v.) cũng như các thuộc tính đối tượng chứa giá trị nguyên thủy.

import React from "react";

function App() {
  const name = "Reed";
  const bio = {
    age: 28,
    isEnglishSpeaker: true
  };

  return (
    <>
      <h1>{name}</h1>
      <h2>I am {bio.age} years old</h2>
      <p>Speaks English: {bio.isEnglishSpeaker}</p>
    </>
  );
}

export default App;

Điều gì sẽ xảy ra nếu chúng ta có một mảng và chúng ta muốn lặp lại mảng đó để hiển thị từng phần tử mảng bên trong một phần tử JSX riêng lẻ?

Đối với điều này, chúng ta có thể sử dụng .map() phương pháp. Nó cho phép chúng ta chuyển đổi từng phần tử trong mảng theo cách chúng ta chỉ định với hàm bên trong.

Lưu ý rằng nó đặc biệt ngắn gọn khi được sử dụng kết hợp với chức năng mũi tên.

/* Note that this isn't exactly the same as the normal JavaScript .map() method, but is very similar. */
import React from "react";

function App() {
  const programmers = ["Reed", "John", "Jane"];

  return (
    <ul>
      {programmers.map(programmer => <li>{programmer}</li>)}
    </ul>
  );
}

export default App;

Có các hương vị khác của phương thức .map() thực hiện các nhiệm vụ liên quan và rất quan trọng để biết vì chúng có thể được xâu chuỗi kết hợp với nhau.

Đọc thêm  Hướng dẫn JS về Phương thức đẩy

Tại sao? Bởi vì .map(), giống như nhiều phương thức mảng, trả về một bản sao nông của mảng mà nó đã lặp lại. Điều này cho phép mảng được trả về của nó được chuyển sang phương thức tiếp theo trong chuỗi.

.filter(), như tên gọi của nó, cho phép chúng ta lọc một số phần tử nhất định ra khỏi mảng của mình. Ví dụ: nếu chúng tôi muốn xóa tất cả tên của các lập trình viên bắt đầu bằng “J”, chúng tôi có thể làm như vậy với .filter():

import React from "react";

function App() {
  const programmers = ["Reed", "John", "Jane"];

  return (
    <ul>
      {/* Returns 'Reed' */}
      {programmers
       .filter(programmer => !programmer.startsWith("J"))
       .map(programmer => <li>{programmer}</li>)}
    </ul>
  );
}

export default App;

Điều quan trọng là phải hiểu rằng cả hai .map().filter() chỉ là những biến thể khác nhau của .reduce() phương thức mảng, có khả năng chuyển đổi các giá trị mảng thành hầu như bất kỳ loại dữ liệu nào, ngay cả các giá trị không phải mảng.

Đây là .reduce() thực hiện các hoạt động tương tự như của chúng tôi .filter() phương pháp trên:

import React from "react";

function App() {
  const programmers = ["Reed", "John", "Jane"];

  return (
    <ul>
      {/* Returns 'Reed' */}
      {programmers
        .reduce((acc, programmer) => {
          if (!programmer.startsWith("J")) {
            return acc.concat(programmer);
          } else {
            return acc;
          }
        }, [])
        .map((programmer) => (
          <li>{programmer}</li>
        ))}
    </ul>
  );
}

export default App;

5. Thủ thuật đối tượng: Tốc ký thuộc tính, Phá hủy, Toán tử trải rộng

Giống như mảng, đối tượng là một cấu trúc dữ liệu mà bạn cần cảm thấy thoải mái khi sử dụng React.

Vì các đối tượng tồn tại vì mục đích lưu trữ khóa-giá trị có tổ chức, không giống như mảng, nên bạn sẽ cần phải rất thoải mái khi truy cập và thao tác các thuộc tính đối tượng.

Để thêm các thuộc tính vào một đối tượng khi bạn tạo nó, bạn đặt tên cho thuộc tính và giá trị tương ứng của nó. Một cách viết tắt rất đơn giản cần nhớ là nếu tên thuộc tính giống với giá trị, bạn chỉ phải liệt kê tên thuộc tính.

Đây là tốc ký thuộc tính đối tượng:

const name = "Reed";

const user = {
  // instead of name: name, we can use...
  name
};

console.log(user.name); // Reed

Cách tiêu chuẩn để truy cập các thuộc tính từ một đối tượng là sử dụng ký hiệu dấu chấm. Tuy nhiên, một cách tiếp cận thuận tiện hơn là phá hủy đối tượng. Nó cho phép chúng ta trích xuất các thuộc tính dưới dạng các biến riêng lẻ cùng tên từ một đối tượng nhất định.

Có vẻ như bạn đang viết ngược một đối tượng, đó là điều làm cho quy trình trở nên trực quan. Nó dễ sử dụng hơn nhiều so với việc phải sử dụng tên đối tượng nhiều lần để truy cập mỗi khi bạn muốn lấy một giá trị từ nó.

const user = {
  name: "Reed",
  age: 28,
  isEnglishSpeaker: true
};
 
// Dot property access
const name = user.name;
const age = user.age;
 
// Object destructuring
const { age, name, isEnglishSpeaker: knowsEnglish } = user;
// Use ':' to rename a value as you destructure it

console.log(knowsEnglish); // true

Bây giờ nếu bạn muốn tạo các đối tượng từ các đối tượng hiện có, bạn có thể liệt kê từng thuộc tính một, nhưng điều đó có thể rất lặp đi lặp lại.

Thay vì sao chép các thuộc tính theo cách thủ công, bạn có thể trải rộng tất cả các thuộc tính của một đối tượng sang một đối tượng khác (khi bạn tạo nó) bằng cách sử dụng toán tử trải rộng đối tượng:

const user = {
  name: "Reed",
  age: 28,
  isEnglishSpeaker: true
};

const firstUser = {
  name: user.name,
  age: user.age,
  isEnglishSpeaker: user.isEnglishSpeaker
};

// Copy all of user's properties into secondUser 
const secondUser = {
  ...user  
};

Điều tuyệt vời về trải rộng đối tượng là bạn có thể trải rộng bao nhiêu đối tượng thành một đối tượng mới tùy thích và bạn có thể sắp xếp chúng như các thuộc tính. Nhưng hãy lưu ý rằng các thuộc tính xuất hiện sau có cùng tên sẽ ghi đè lên các thuộc tính trước đó:

const user = {
  name: "Reed",
  age: 28
};

const moreUserInfo = {
  age: 70,
  country: "USA"
};

// Copy all of user's properties into secondUser 
const secondUser = {
  ...user,
  ...moreUserInfo,
   computer: "MacBook Pro"
};

console.log(secondUser);
// { name: "Reed", age: 70, country: "USA", computer: "Macbook Pro" }

6: Hứa hẹn + Cú pháp Async/Await

Hầu như mọi ứng dụng React đều bao gồm mã không đồng bộ mã mất một lượng thời gian không xác định để được thực thi. Đặc biệt nếu bạn cần lấy hoặc thay đổi dữ liệu từ API bên ngoài bằng các tính năng của trình duyệt như Tìm nạp API hoặc thư viện của bên thứ ba trục.

Các lời hứa được sử dụng để giải quyết mã không đồng bộ để làm cho nó giải quyết giống như mã đồng bộ, bình thường mà chúng ta có thể đọc từ trên xuống dưới.

Theo truyền thống, các lời hứa sử dụng các cuộc gọi lại để giải quyết mã không đồng bộ của chúng tôi. chúng tôi sử dụng .then() gọi lại để giải quyết các lời hứa đã giải quyết thành công, trong khi chúng tôi sử dụng .catch() gọi lại để giải quyết các lời hứa phản hồi có lỗi.

Đây là một ví dụ thực tế về việc sử dụng React để tìm nạp dữ liệu từ API GitHub của tôi bằng cách sử dụng API Tìm nạp để hiển thị ảnh hồ sơ của tôi. Dữ liệu được giải quyết bằng lời hứa:

/* Go to react.new and paste this code in to see it work! */
import React from 'react';
 
const App = () => {
  const [avatar, setAvatar] = React.useState('');
 
  React.useEffect(() => {
    /* 
      The first .then() lets us get JSON data from the response.
      The second .then() gets the url to my avatar and puts it in state. 
    */
    fetch('https://api.github.com/users/reedbarger')
      .then(response => response.json())
      .then(data => setAvatar(data.avatar_url))
      .catch(error => console.error("Error fetching data: ", error);
  }, []);
 
  return (
    <img src={avatar} alt="Reed Barger" />
  );
};
 
export default App;

Thay vì luôn cần sử dụng các cuộc gọi lại để giải quyết dữ liệu của chúng ta từ một lời hứa, chúng ta có thể sử dụng một cú pháp sạch trông giống với mã đồng bộ, được gọi là cú pháp không đồng bộ/chờ đợi.

Đọc thêm  Tìm hiểu kiến ​​thức cơ bản về phát triển web – Giải thích về HTML, CSS và JavaScript cho người mới bắt đầu

Các từ khóa không đồng bộ và chờ đợi chỉ được sử dụng với các chức năng (các chức năng JavaScript thông thường, không phải các thành phần chức năng React).

Để sử dụng chúng, chúng tôi cần đảm bảo rằng mã không đồng bộ của chúng tôi nằm trong một chức năng được thêm vào trước từ khóa async. Bất kỳ giá trị của lời hứa sau đó có thể được giải quyết bằng cách đặt từ khóa await trước nó.

/* Go to react.new and paste this code in to see it work! */
import React from "react";

const App = () => {
  const [avatar, setAvatar] = React.useState("");

  React.useEffect(() => {
    /* 
	  Note that because the function passed to useEffect cannot be async, we must create a separate function for our promise to be resolved in (fetchAvatar)
    */
    async function fetchAvatar() {
      const response = await fetch("https://api.github.com/users/reedbarger");
      const data = await response.json();
      setAvatar(data.avatar_url);
    }

    fetchAvatar();
  }, []);

  return <img src={avatar} alt="Reed Barger" />;
};

export default App;

chúng tôi sử dụng .catch() gọi lại để xử lý lỗi trong các lời hứa truyền thống, nhưng làm cách nào để bạn bắt lỗi với async/await?

chúng tôi vẫn sử dụng .catch() và khi chúng tôi gặp lỗi, chẳng hạn như khi chúng tôi nhận được phản hồi từ API nằm trong phạm vi trạng thái 200 hoặc 300:

/* Go to react.new and paste this code in to see it work! */
import React from "react";

const App = () => {
  const [avatar, setAvatar] = React.useState("");

  React.useEffect(() => {
    async function fetchAvatar() {
      /* Using an invalid user to create a 404 (not found) error */
      const response = await fetch("https://api.github.com/users/reedbarge");
      if (!response.ok) {
        const message = `An error has occured: ${response.status}`;
        /* In development, you'll see this error message displayed on your screen */
        throw new Error(message);
      }
      const data = await response.json();

      setAvatar(data.avatar_url);
    }

    fetchAvatar();
  }, []);

  return <img src={avatar} alt="Reed Barger" />;
};

export default App;

7. Mô-đun ES + Cú pháp nhập/xuất

ES6 đã cho chúng tôi khả năng dễ dàng chia sẻ mã giữa các tệp JavaScript của riêng chúng tôi cũng như các thư viện của bên thứ ba bằng cách sử dụng mô-đun ES.

Ngoài ra, khi tận dụng các công cụ như Webpack, chúng tôi có thể nhập nội dung như hình ảnh và svgs, cũng như tệp CSS và sử dụng chúng làm giá trị động trong mã của mình.

/* We're bringing into our file a library (React), a png image, and CSS styles */
import React from 'react';
import logo from '../img/site-logo.png';
import '../styles/app.css';
 
function App() {
  return (
    <div>
      Welcome!
      <img src={logo} alt="Site logo" />
    </div>
  );
}
 
export default App;

Ý tưởng đằng sau các mô-đun ES là có thể chia mã JavaScript của chúng tôi thành các tệp khác nhau, để biến nó thành mô-đun hoặc có thể tái sử dụng trên ứng dụng của chúng tôi.

Đối với mã JavaScript, chúng ta có thể nhập và xuất các biến và hàm. Có hai cách nhập và xuất, như nhập khẩu / xuất khẩu được đặt tên và như nhập/xuất mặc định.

Chỉ có thể có một thứ mà chúng tôi thực hiện nhập hoặc xuất mặc định cho mỗi tệp và chúng tôi có thể tạo bao nhiêu thứ có tên là nhập/xuất tùy thích. Ví dụ:

// constants.js
export const name = "Reed";

export const age = 28;

export default function getName() {
  return name;   
}

// app.js
// Notice that named exports are imported between curly braces
import getName, { name, age } from '../constants.js';

console.log(name, age, getName());

Chúng tôi cũng có thể viết tất cả các bản xuất ở cuối tệp thay vì bên cạnh mỗi biến hoặc hàm:

// constants.js
const name = "Reed";

const age = 28;

function getName() {
  return name;   
}

export { name, age };
export default getName;

// app.js
import getName, { name, age } from '../constants.js';

console.log(name, age, getName());

Bạn cũng có thể đặt bí danh hoặc đổi tên những gì bạn đang nhập bằng cách sử dụng as từ khóa cho nhập khẩu được đặt tên. Lợi ích của việc xuất mặc định là chúng có thể được đặt tên theo bất cứ thứ gì bạn muốn.

// constants.js
const name = "Reed";

const age = 28;

function getName() {
  return name;   
}

export { name, age };
export default getName;

// app.js
import getMyName, { name as myName, age as myAge } from '../constants.js';

console.log(myName, myAge, getMyName());

Trong thời gian cần thiết để xem chương trình truyền hình yêu thích của bạn, bạn có thể bắt đầu sự nghiệp trị giá 100.000 đô la/năm với React.

Trong khóa đào tạo React cao cấp này, bạn có thể mở khóa kiến ​​thức, kỹ năng và sự tự tin mang lại kết quả thay đổi cuộc sống bằng đô la thực.

Có được thông tin nội bộ mà hàng trăm nhà phát triển đã sử dụng để thành thạo React, tìm được công việc mơ ước và kiểm soát tương lai của họ:

Bootcamp phản ứng
Nhấn vào đây để được thông báo khi khóa học mở



Zik.vn – Biên dịch & Biên soạn Lại

spot_img

Create a website from scratch

Just drag and drop elements in a page to get started with Newspaper Theme.

Buy Now ⟶

Bài viết liên quang

DMCA.com Protection Status