Skip to main content
โšก Calmops

React: Getting Started and JSX

React: Getting Started and JSX

React is a powerful library for building user interfaces. This article covers JSX, components, props, and fundamental React concepts.

Introduction

React provides:

  • Component-based architecture
  • Declarative UI
  • Reusable components
  • Efficient rendering
  • Developer experience

Understanding React helps you:

  • Build interactive UIs
  • Create reusable components
  • Manage application state
  • Build scalable applications
  • Improve development productivity

Setting Up React

Create React App

# โœ… Good: Create React app
npx create-react-app my-app
cd my-app
npm start

# โœ… Good: With TypeScript
npx create-react-app my-app --template typescript

# โœ… Good: Vite (faster alternative)
npm create vite@latest my-app -- --template react
cd my-app
npm install
npm run dev

Project Structure

my-app/
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ components/
โ”‚   โ”‚   โ”œโ”€โ”€ Header.jsx
โ”‚   โ”‚   โ”œโ”€โ”€ Footer.jsx
โ”‚   โ”‚   โ””โ”€โ”€ Button.jsx
โ”‚   โ”œโ”€โ”€ pages/
โ”‚   โ”‚   โ”œโ”€โ”€ Home.jsx
โ”‚   โ”‚   โ””โ”€โ”€ About.jsx
โ”‚   โ”œโ”€โ”€ App.jsx
โ”‚   โ”œโ”€โ”€ index.css
โ”‚   โ””โ”€โ”€ main.jsx
โ”œโ”€โ”€ public/
โ”œโ”€โ”€ package.json
โ””โ”€โ”€ vite.config.js

JSX Basics

Understanding JSX

// โœ… Good: JSX syntax
const element = <h1>Hello, React!</h1>;

// โœ… Good: JSX with expressions
const name = 'John';
const greeting = <h1>Hello, {name}!</h1>;

// โœ… Good: JSX with attributes
const image = <img src="logo.png" alt="Logo" />;

// โœ… Good: JSX with children
const card = (
  <div className="card">
    <h2>Title</h2>
    <p>Content</p>
  </div>
);

// โœ… Good: JSX with conditional rendering
const isLoggedIn = true;
const ui = isLoggedIn ? <h1>Welcome!</h1> : <h1>Please log in</h1>;

JSX Rules

// โœ… Good: Single root element
const element = (
  <div>
    <h1>Title</h1>
    <p>Content</p>
  </div>
);

// โŒ Bad: Multiple root elements
// const element = (
//   <h1>Title</h1>
//   <p>Content</p>
// );

// โœ… Good: Close all tags
const element = <img src="logo.png" />;

// โœ… Good: Use className instead of class
const element = <div className="container">Content</div>;

// โœ… Good: Use camelCase for attributes
const element = <input onChange={handleChange} />;

Components

Functional Components

// โœ… Good: Functional component
function Welcome() {
  return <h1>Hello, React!</h1>;
}

// โœ… Good: Arrow function component
const Welcome = () => {
  return <h1>Hello, React!</h1>;
};

// โœ… Good: Component with JSX
const Card = () => {
  return (
    <div className="card">
      <h2>Card Title</h2>
      <p>Card content</p>
    </div>
  );
};

// โœ… Good: Export component
export default Welcome;

Using Components

// โœ… Good: Use component
function App() {
  return (
    <div>
      <Welcome />
      <Card />
    </div>
  );
}

// โœ… Good: Component composition
function Dashboard() {
  return (
    <div>
      <Header />
      <MainContent />
      <Footer />
    </div>
  );
}

Props

Passing Props

// โœ… Good: Component with props
function Greeting({ name, age }) {
  return (
    <div>
      <h1>Hello, {name}!</h1>
      <p>You are {age} years old</p>
    </div>
  );
}

// โœ… Good: Using component with props
function App() {
  return <Greeting name="John" age={30} />;
}

// โœ… Good: Default props
function Button({ label = 'Click me', onClick }) {
  return <button onClick={onClick}>{label}</button>;
}

// โœ… Good: Props with children
function Card({ title, children }) {
  return (
    <div className="card">
      <h2>{title}</h2>
      <div>{children}</div>
    </div>
  );
}

// Usage
<Card title="My Card">
  <p>Card content</p>
</Card>

Props Validation

// โœ… Good: PropTypes validation
import PropTypes from 'prop-types';

function User({ name, age, email }) {
  return (
    <div>
      <h1>{name}</h1>
      <p>Age: {age}</p>
      <p>Email: {email}</p>
    </div>
  );
}

User.propTypes = {
  name: PropTypes.string.isRequired,
  age: PropTypes.number,
  email: PropTypes.string.isRequired
};

// โœ… Good: TypeScript types
interface UserProps {
  name: string;
  age?: number;
  email: string;
}

function User({ name, age, email }: UserProps) {
  return (
    <div>
      <h1>{name}</h1>
      <p>Age: {age}</p>
      <p>Email: {email}</p>
    </div>
  );
}

State

Using State

import { useState } from 'react';

// โœ… Good: useState hook
function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        Increment
      </button>
    </div>
  );
}

// โœ… Good: Multiple state variables
function Form() {
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');

  return (
    <form>
      <input
        value={name}
        onChange={(e) => setName(e.target.value)}
        placeholder="Name"
      />
      <input
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        placeholder="Email"
      />
    </form>
  );
}

// โœ… Good: State with objects
function User() {
  const [user, setUser] = useState({
    name: 'John',
    age: 30,
    email: '[email protected]'
  });

  const updateName = (newName) => {
    setUser({ ...user, name: newName });
  };

  return (
    <div>
      <h1>{user.name}</h1>
      <button onClick={() => updateName('Jane')}>
        Change Name
      </button>
    </div>
  );
}

Events

Handling Events

// โœ… Good: Event handlers
function Button() {
  const handleClick = () => {
    console.log('Button clicked');
  };

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

// โœ… Good: Event with parameters
function List() {
  const handleItemClick = (id) => {
    console.log(`Item ${id} clicked`);
  };

  return (
    <ul>
      <li onClick={() => handleItemClick(1)}>Item 1</li>
      <li onClick={() => handleItemClick(2)}>Item 2</li>
    </ul>
  );
}

// โœ… Good: Form events
function Form() {
  const handleSubmit = (e) => {
    e.preventDefault();
    console.log('Form submitted');
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" />
      <button type="submit">Submit</button>
    </form>
  );
}

// โœ… Good: Input events
function Input() {
  const [value, setValue] = useState('');

  return (
    <input
      value={value}
      onChange={(e) => setValue(e.target.value)}
      onFocus={() => console.log('Focused')}
      onBlur={() => console.log('Blurred')}
    />
  );
}

Practical Examples

Todo App

import { useState } from 'react';

function TodoApp() {
  const [todos, setTodos] = useState([]);
  const [input, setInput] = useState('');

  const addTodo = () => {
    if (input.trim()) {
      setTodos([...todos, { id: Date.now(), text: input }]);
      setInput('');
    }
  };

  const removeTodo = (id) => {
    setTodos(todos.filter(todo => todo.id !== id));
  };

  return (
    <div>
      <h1>Todo App</h1>
      <input
        value={input}
        onChange={(e) => setInput(e.target.value)}
        placeholder="Add a todo"
      />
      <button onClick={addTodo}>Add</button>
      <ul>
        {todos.map(todo => (
          <li key={todo.id}>
            {todo.text}
            <button onClick={() => removeTodo(todo.id)}>Delete</button>
          </li>
        ))}
      </ul>
    </div>
  );
}

export default TodoApp;

User Profile

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  const fetchUser = async () => {
    try {
      const response = await fetch(`/api/users/${userId}`);
      const data = await response.json();
      setUser(data);
    } catch (error) {
      console.error('Error fetching user:', error);
    } finally {
      setLoading(false);
    }
  };

  if (loading) return <p>Loading...</p>;
  if (!user) return <p>User not found</p>;

  return (
    <div>
      <h1>{user.name}</h1>
      <p>Email: {user.email}</p>
      <p>Age: {user.age}</p>
    </div>
  );
}

export default UserProfile;

Best Practices

  1. Use functional components:

    // โœ… Good
    function Welcome() {
      return <h1>Hello</h1>;
    }
    
    // โŒ Bad (class components are outdated)
    class Welcome extends React.Component {
      render() {
        return <h1>Hello</h1>;
      }
    }
    
  2. Keep components small:

    // โœ… Good
    function Button({ label, onClick }) {
      return <button onClick={onClick}>{label}</button>;
    }
    
    // โŒ Bad (too much logic)
    function ComplexComponent() {
      // 500 lines of code
    }
    
  3. Use keys in lists:

    // โœ… Good
    {items.map(item => <Item key={item.id} {...item} />)}
    
    // โŒ Bad
    {items.map((item, index) => <Item key={index} {...item} />)}
    

Common Mistakes

  1. Mutating state directly:

    // โŒ Bad
    state.name = 'John';
    
    // โœ… Good
    setState({ ...state, name: 'John' });
    
  2. Missing keys in lists:

    // โŒ Bad
    {items.map(item => <Item {...item} />)}
    
    // โœ… Good
    {items.map(item => <Item key={item.id} {...item} />)}
    

Summary

React fundamentals are essential. Key takeaways:

  • Understand JSX syntax
  • Create functional components
  • Use props for data passing
  • Manage state with hooks
  • Handle events properly
  • Keep components small
  • Use keys in lists
  • Follow best practices

Next Steps

Comments