വേഗം തുടങ്ങാം

റീയാക്ട് ഡോക്യുമെന്റേഷനിലേക്ക് സ്വാഗതം! ദിവസേന ഒരാൾ ഉപയോഗിക്കാൻ സാധ്യത ഉള്ള 80% ആശയങ്ങളും ഈ ഒരു പേജിലൂടെ നിങ്ങൾക്ക് പഠിക്കാം.

ഈ ചാപ്റ്ററിൽ പഠിക്കുന്നത്

  • എങ്ങനെ componentകൾ ഉണ്ടാക്കാം?
  • componentകളെ എങ്ങനെ style ചെയ്യാം?
  • എങ്ങനെ componentൽ data കാണിക്കാം?
  • conditionകളും listകളും എങ്ങനെ render ചെയ്യാം?
  • events നടക്കുമ്പോൾ എങ്ങനെ സ്ക്രീനിൽ മാറ്റങ്ങൾ വരുത്താം?
  • എങ്ങനെ രണ്ടു componentsനിടയിൽ data പങ്കിടാം?

എങ്ങനെ componentകൾ ഉണ്ടാക്കാം

നമ്മൾ ഒരു ബ്രൗസറിന്റെ സ്‌ക്രീനിൽ കാണുന്നതിനെ UI (User Interface) എന്ന് പറയാം. ഒരു ബട്ടൺ, അല്ലെങ്കിൽ ഒരു പേയ്മെന്റ് പേജ് ഒക്കെ ഒരു UIടെ ഭാഗമാണ്. സ്വന്തമായി യുക്തി(logic)യും രൂപവും ഉള്ള ഒരു UI (User Interface)ന്റെ ഒരു ഭാഗത്തെ നമുക്ക് React component എന്ന് വിളിക്കാം. എല്ലാ React അപ്ലിക്കേഷനുകളും components കൊണ്ട് നിർമിച്ചിരിക്കുന്നു. അതായത് ഒരു ബട്ടൺ, അല്ലെങ്കിൽ ഒരു മുഴുവൻ പേജ് ഒക്കെ നമുക്ക് component ആയിട്ട് ഉണ്ടാക്കാം.

ചുരുക്കി പറഞ്ഞാൽ “markup” return ചെയ്യുന്ന ഒരു javascript function ആണ് ഒരു React component:

function MyButton() {
return (
<button>I'm a button</button>
);
}

മുകളിൽ ഒരു MyButton component നിർവചിച്ചിരിക്കുന്നു. ചിലപ്പോൾ ഈ component വേറൊരു componentന്റെ ഉള്ളിൽ ഉപയോഗിക്കേണ്ടി വരും:

export default function MyApp() {
return (
<div>
<h1>Welcome to my app</h1>
<MyButton />
</div>
);
}

<MyButton /> ഒരു ക്യാപിറ്റൽ ലെറ്റർ വെച്ചു സ്റ്റാർട്ട് ചെയ്യുന്നത് ശ്രദ്ധിച്ചോ? എല്ലാ React componentsഉം അങ്ങനെ ആണ് തുടങ്ങുക. componentകൾ എല്ലാം ക്യാപിറ്റൽ ലെറ്റർ വെച്ചു തുടങ്ങും, അതുപോലെ HTML ടാഗുകൾ ലോവർ കേസും ആയിരിക്കും.

മുകളിലെ കോഡ് താഴെ ഉള്ളത് പോലെ ആണ് ഒരു ബ്രൗസറിൽ കാണുക. ഒരു ബ്രൗസറിൽ React കാണിക്കുന്നതിനെ നമുക്കു React render ചെയ്യുക എന്നും പറയാം. അതായത് താഴെ ഇടത് ഭാഗത്തുള്ള കോഡ് React വലത് ഭാഗത്തു render ചെയ്തിരിക്കുന്നു

function MyButton() {
  return (
    <button>
      I'm a button
    </button>
  );
}

export default function MyApp() {
  return (
    <div>
      <h1>Welcome to my app</h1>
      <MyButton />
    </div>
  );
}

നമ്മുടെ കോഡിൽ export default എന്ന ഭാഗം ശ്രദ്ധിച്ചോ? അങ്ങനെ ആണ് നമ്മൾ ഒരു ഫയലിലെ മെയിൻ componentനെ export ചെയ്യുക. ഈ export ഭാഗം കൂടുതൽ മനസ്സിലാക്കാൻ, MDN അതുപോലെ javascript.info ലിങ്കുകൾ ഉപയോഗിക്കാം. ഒരു component export ചെയ്താൽ മാത്രമേ നമുക്ക് മറ്റു ഫയലുകളിൽ ഉപയോഗിക്കാൻ കഴിയുകയുള്ളു.

JSX ഉപയോഗിച്ചു markup എഴുതുമ്പോൾ

നമ്മുടെ componentലെ (MyApp) കാണാൻ HTML പോലെ ഉള്ള markup ശ്രദ്ധിച്ചോ? അതിനെ JSX എന്ന് പറയുന്നു. ഒരു React Componentനു JSX വേണം എന്ന് നിർബന്ധമില്ല, എങ്കിലും ഒരു വിധ എല്ലാ പ്രൊജെക്ടുകളും എളുപ്പത്തിൽ component എഴുതാൻ JSX ഉപയോഗിക്കുന്നു. ഈ പേജിൽ പറയുന്ന എല്ലാ ടൂൾസും വേറെ ഒന്നും ചെയ്യാതെ തന്നെ JSX സപ്പോർട്ട് ചെയ്യും.

റൂൾസിന്റെ കാര്യത്തിൽ HTML വെച്ച് നോക്കുമ്പോൾ JSX കുറച്ചു കൂടെ കര്‍ശനമാണ്. <br /> പോലുള്ള റ്റാഗുകൾ കറക്റ്റ് ക്ലോസ് ചെയ്യണം, തന്നെയുമല്ല, ഒരു component ഒന്നിൽ കൂടുതൽ JSX റ്റാഗുകൾ return ചെയ്യരുത്. അങ്ങനെ ചെയ്യണമെങ്കിൽ എല്ലാ ടാഗുകളും ഒരു പാരന്റ് ടാഗിൽ പൊതിഞ്ഞു return ചെയ്യണം. ഉദാഹരണത്തിന് ഒരു <div>...</div> അല്ലെങ്കിൽ ഒരു <>...</> വെച്ചു പൊതിഞ്ഞാലേ നമ്മുടെ JSX ശെരി ആവുകയുള്ളൂ:

function AboutPage() {
return (
<>
<h1>About</h1>
<p>Hello there.<br />How do you do?</p>
</>
);
}

നിങ്ങൾക്കു കുറെ അധികം HTML റ്റാഗ്സ് JSXലേക്ക് മാറ്റാൻ ഉണ്ടെങ്കിൽ ഈ ഒരു ഓൺലൈൻ കൺവെർട്ടർ ഉപയോഗിക്കാം

componentകളെ എങ്ങനെ style ചെയ്യാം?

React componentൽ ഒരു CSS ക്ലാസിനു വേണ്ടി നമ്മൾ className ഉപയോഗിക്കണം. HTMLൽ ഉള്ള class ടാഗും React className ടാഗും ഒരുപോലെ ആണ് വർക്ക് ചെയ്യുക.

<img className="avatar" />

ശേഷം വേണ്ട CSS വേറെ ഒരു ഫൈലിൽ എഴുതുക

/* In your CSS */
.avatar {
border-radius: 50%;
}

ഇതിനു ശേഷം എങ്ങനെ ആണ് നമ്മൾ ഈ CSS ഫയൽ പ്രോജെക്ടിൽ ആഡ് ചെയ്യുന്നത് എന്നതിന് Reactനു പ്രത്യേക റൂൾ ഒന്നുമില്ല. വേണമെങ്കിൽ നേരിട്ട് ഒരു link HTMLൽ കൊടുക്കാം. ഇനി നിങ്ങൾ ഒരു ബിൽഡ് ടൂലോ ഫ്രെയിംവർക്കോ ഉപയോഗിച്ചു CSS ആഡ് ചെയ്താലും ഇത് വർക്ക് ചെയ്യും.

എങ്ങനെ componentൽ data കാണിക്കാം?

JSX ഉപയോഗിച്ചപ്പോൾ നമുക്കു JavaScriptന്റെ ഉള്ളിൽ markup എഴുതാൻ സാധിച്ചു. JSXന്റെ ഉള്ളിൽ Curly braces ഉപയോഗിച്ചാൽ നമുക്ക് തിരിച്ചു JSXന്റെ ഉള്ളിൽ JavaScript റൺ ചെയ്യാം. താഴെ ഉള്ള example നോക്കൂ, നമ്മുടെ കോഡിലെ user.name എന്ന ഒരു വേരിയബിന്റെ വാല്യൂ, ഇങ്ങനെ കൊടുക്കുമ്പോൾ സ്‌ക്രീനിൽ render ചെയ്യും:

return (
<h1>
{user.name}
</h1>
);

ഇനി നമുക്ക് JSXന്റെ ഏതേലും attributes ആണ് ഇങ്ങനെ മാറ്റേണ്ടതെങ്കിലും ഈ “Curly braces” തന്നെ ഉപയോഗിക്കാം. ഉദാഹരണത്തിന്, className="avatar" എന്നത് "avatar" എന്ന വാചകം (string) CSS ക്ലാസ്സായി കൈമാറുന്നു, എന്നാൽ src={user.imageUrl} എന്നത് user.imageUrlന്റെ വാല്യൂ എടുത്ത് ആ വാല്യൂ ആണ് CSS ക്ലാസ്സായിട്ടു കൊടുക്കുക:

return (
<img
className="avatar"
src={user.imageUrl}
/>
);

JSX Curly braces ഇതിലും കോംപ്ലക്സ് ആയിട്ടുള്ള കാര്യങ്ങൾക്കും ഉപയോഗിക്കാം, for example, string concatenation:

const user = {
  name: 'Hedy Lamarr',
  imageUrl: 'https://i.imgur.com/yXOvdOSs.jpg',
  imageSize: 90,
};

export default function Profile() {
  return (
    <>
      <h1>{user.name}</h1>
      <img
        className="avatar"
        src={user.imageUrl}
        alt={'Photo of ' + user.name}
        style={{
          width: user.imageSize,
          height: user.imageSize
        }}
      />
    </>
  );
}

മുകളിൽ, style={{}} എന്നത് ഒരു സ്പെഷ്യൽ syntax ഒന്നുമല്ല. ഒരു സാധാരണ object {} നേരത്തെ പറഞ്ഞ Curly bracesന്റെ (style={ }) ഉള്ളിൽ വന്നതാണ്. ഇവിടെ നമ്മൾക്കു കൊടുക്കേണ്ട styles, JavaScript വേരിയബിളിൽ നിന്ന് വന്നപ്പോൾ നമ്മൾ Curly braces ഉപയോഗിച്ചു എന്ന് മാത്രം.

Conditional rendering

In React, there is no special syntax for writing conditions. Instead, you’ll use the same techniques as you use when writing regular JavaScript code. For example, you can use an if statement to conditionally include JSX:

let content;
if (isLoggedIn) {
content = <AdminPanel />;
} else {
content = <LoginForm />;
}
return (
<div>
{content}
</div>
);

If you prefer more compact code, you can use the conditional ? operator. Unlike if, it works inside JSX:

<div>
{isLoggedIn ? (
<AdminPanel />
) : (
<LoginForm />
)}
</div>

When you don’t need the else branch, you can also use a shorter logical && syntax:

<div>
{isLoggedIn && <AdminPanel />}
</div>

All of these approaches also work for conditionally specifying attributes. If you’re unfamiliar with some of this JavaScript syntax, you can start by always using if...else.

Rendering lists

You will rely on JavaScript features like for loop and the array map() function to render lists of components.

For example, let’s say you have an array of products:

const products = [
{ title: 'Cabbage', id: 1 },
{ title: 'Garlic', id: 2 },
{ title: 'Apple', id: 3 },
];

Inside your component, use the map() function to transform an array of products into an array of <li> items:

const listItems = products.map(product =>
<li key={product.id}>
{product.title}
</li>
);

return (
<ul>{listItems}</ul>
);

Notice how <li> has a key attribute. For each item in a list, you should pass a string or a number that uniquely identifies that item among its siblings. Usually, a key should be coming from your data, such as a database ID. React uses your keys to know what happened if you later insert, delete, or reorder the items.

const products = [
  { title: 'Cabbage', isFruit: false, id: 1 },
  { title: 'Garlic', isFruit: false, id: 2 },
  { title: 'Apple', isFruit: true, id: 3 },
];

export default function ShoppingList() {
  const listItems = products.map(product =>
    <li
      key={product.id}
      style={{
        color: product.isFruit ? 'magenta' : 'darkgreen'
      }}
    >
      {product.title}
    </li>
  );

  return (
    <ul>{listItems}</ul>
  );
}

Responding to events

You can respond to events by declaring event handler functions inside your components:

function MyButton() {
function handleClick() {
alert('You clicked me!');
}

return (
<button onClick={handleClick}>
Click me
</button>
);
}

Notice how onClick={handleClick} has no parentheses at the end! Do not call the event handler function: you only need to pass it down. React will call your event handler when the user clicks the button.

Updating the screen

Often, you’ll want your component to “remember” some information and display it. For example, maybe you want to count the number of times a button is clicked. To do this, add state to your component.

First, import useState from React:

import { useState } from 'react';

Now you can declare a state variable inside your component:

function MyButton() {
const [count, setCount] = useState(0);
// ...

You’ll get two things from useState: the current state (count), and the function that lets you update it (setCount). You can give them any names, but the convention is to write [something, setSomething].

The first time the button is displayed, count will be 0 because you passed 0 to useState(). When you want to change state, call setCount() and pass the new value to it. Clicking this button will increment the counter:

function MyButton() {
const [count, setCount] = useState(0);

function handleClick() {
setCount(count + 1);
}

return (
<button onClick={handleClick}>
Clicked {count} times
</button>
);
}

React will call your component function again. This time, count will be 1. Then it will be 2. And so on.

If you render the same component multiple times, each will get its own state. Click each button separately:

import { useState } from 'react';

export default function MyApp() {
  return (
    <div>
      <h1>Counters that update separately</h1>
      <MyButton />
      <MyButton />
    </div>
  );
}

function MyButton() {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <button onClick={handleClick}>
      Clicked {count} times
    </button>
  );
}

Notice how each button “remembers” its own count state and doesn’t affect other buttons.

Using Hooks

Functions starting with use are called Hooks. useState is a built-in Hook provided by React. You can find other built-in Hooks in the API reference. You can also write your own Hooks by combining the existing ones.

Hooks are more restrictive than other functions. You can only call Hooks at the top of your components (or other Hooks). If you want to use useState in a condition or a loop, extract a new component and put it there.

Sharing data between components

In the previous example, each MyButton had its own independent count, and when each button was clicked, only the count for the button clicked changed:

Diagram showing a tree of three components, one parent labeled MyApp and two children labeled MyButton. Both MyButton components contain a count with value zero.
Diagram showing a tree of three components, one parent labeled MyApp and two children labeled MyButton. Both MyButton components contain a count with value zero.

Initially, each MyButton’s count state is 0

The same diagram as the previous, with the count of the first child MyButton component highlighted indicating a click with the count value incremented to one. The second MyButton component still contains value zero.
The same diagram as the previous, with the count of the first child MyButton component highlighted indicating a click with the count value incremented to one. The second MyButton component still contains value zero.

The first MyButton updates its count to 1

However, often you’ll need components to share data and always update together.

To make both MyButton components display the same count and update together, you need to move the state from the individual buttons “upwards” to the closest component containing all of them.

In this example, it is MyApp:

Diagram showing a tree of three components, one parent labeled MyApp and two children labeled MyButton. MyApp contains a count value of zero which is passed down to both of the MyButton components, which also show value zero.
Diagram showing a tree of three components, one parent labeled MyApp and two children labeled MyButton. MyApp contains a count value of zero which is passed down to both of the MyButton components, which also show value zero.

Initially, MyApp’s count state is 0 and is passed down to both children

The same diagram as the previous, with the count of the parent MyApp component highlighted indicating a click with the value incremented to one. The flow to both of the children MyButton components is also highlighted, and the count value in each child is set to one indicating the value was passed down.
The same diagram as the previous, with the count of the parent MyApp component highlighted indicating a click with the value incremented to one. The flow to both of the children MyButton components is also highlighted, and the count value in each child is set to one indicating the value was passed down.

On click, MyApp updates its count state to 1 and passes it down to both children

Now when you click either button, the count in MyApp will change, which will change both of the counts in MyButton. Here’s how you can express this in code.

First, move the state up from MyButton into MyApp:

export default function MyApp() {
const [count, setCount] = useState(0);

function handleClick() {
setCount(count + 1);
}

return (
<div>
<h1>Counters that update separately</h1>
<MyButton />
<MyButton />
</div>
);
}

function MyButton() {
// ... we're moving code from here ...
}

Then, pass the state down from MyApp to each MyButton, together with the shared click handler. You can pass information to MyButton using the JSX curly braces, just like you previously did with built-in tags like <img>:

export default function MyApp() {
const [count, setCount] = useState(0);

function handleClick() {
setCount(count + 1);
}

return (
<div>
<h1>Counters that update together</h1>
<MyButton count={count} onClick={handleClick} />
<MyButton count={count} onClick={handleClick} />
</div>
);
}

The information you pass down like this is called props. Now the MyApp component contains the count state and the handleClick event handler, and passes both of them down as props to each of the buttons.

Finally, change MyButton to read the props you have passed from its parent component:

function MyButton({ count, onClick }) {
return (
<button onClick={onClick}>
Clicked {count} times
</button>
);
}

When you click the button, the onClick handler fires. Each button’s onClick prop was set to the handleClick function inside MyApp, so the code inside of it runs. That code calls setCount(count + 1), incrementing the count state variable. The new count value is passed as a prop to each button, so they all show the new value. This is called “lifting state up”. By moving state up, you’ve shared it between components.

import { useState } from 'react';

export default function MyApp() {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <div>
      <h1>Counters that update together</h1>
      <MyButton count={count} onClick={handleClick} />
      <MyButton count={count} onClick={handleClick} />
    </div>
  );
}

function MyButton({ count, onClick }) {
  return (
    <button onClick={onClick}>
      Clicked {count} times
    </button>
  );
}

Next Steps

By now, you know the basics of how to write React code!

Check out the Tutorial to put them into practice and build your first mini-app with React.