React Lecture: Supplying Data to the Component Tree and Refactoring a To Do App with Context

React is one of the most popular libraries for building modern web applications. This is due to its component-based architecture, reusability, and the ease of managing complex UIs. In this tutorial, we will explore how to supply data to the component tree using React’s Context API and how to refactor it to create a simple Todo application.

1. Basic Concepts of React

React is a collection of components that make up the user interface. Components have state and props, which determine how the UI is rendered.

1.1 State and Props

State represents the internal data of a component, which can change based on user input or network requests. On the other hand, props are the data passed from a parent component to a child component.

1.2 Component Tree

A React application is arranged in a tree structure made up of multiple components. This tree structure manages the flow of data from parent to child components.

2. Introduction to Context API

The Context API is used in React to pass data to components deeply nested within the component tree. It allows data to be supplied without having to pass props through multiple levels, helping to reduce the complexity of prop drilling.

2.1 Creating Context

To create Context, you first need to use React’s createContext function.

import React, { createContext, useContext, useState } from 'react';

const MyContext = createContext(); // Create Context

2.2 Provider and Consumer

Use the Provider component of the Context to pass data down to child components. The Provider supplies data that can be accessed by all descendant components.

<MyContext.Provider value={/* context value */}>
    {/* children */}
</MyContext.Provider>

2.3 Using Context

To use Context in a child component, you retrieve the data using the useContext hook.

const value = useContext(MyContext); // Use Context

3. Setting Up the Todo App Structure

Now, let’s create a simple Todo app using Context API. First, we will set up the basic component structure.

3.1 Basic Component Structure

The Todo app consists of the following components.

  • App: The component that wraps the entire app
  • TodoProvider: The Provider component that manages the state of the Todo list
  • TodoList: The component that renders the list of Todo items
  • TodoItem: The component that renders individual Todo items
  • AddTodo: The component for adding new Todo items

3.2 Writing the App Code

First, we will write the TodoProvider component to manage the state of the Todo list.

const TodoProvider = ({ children }) => {
    const [todos, setTodos] = useState([]);

    const addTodo = (todo) => {
        setTodos([...todos, todo]);
    };

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

    return (
        <MyContext.Provider value={{ todos, addTodo, removeTodo }}>
            {children}
        </MyContext.Provider>
    );
};

Then we will write the TodoList and AddTodo components.

const TodoList = () => {
    const { todos, removeTodo } = useContext(MyContext);

    return (
        <ul>
            {todos.map(todo => (
                <TodoItem key={todo.id} todo={todo} onRemove={removeTodo} />
            ))}</ul>
    );
};

const AddTodo = () => {
    const { addTodo } = useContext(MyContext);
    const [inputValue, setInputValue] = useState('');

    const handleSubmit = (e) => {
        e.preventDefault();
        if (!inputValue) return;
        
        addTodo({ id: Date.now(), text: inputValue });
        setInputValue('');
    };

    return (
        <form onSubmit={handleSubmit}>
            <input 
                type="text" 
                value={inputValue} 
                onChange={(e) => setInputValue(e.target.value)} 
                placeholder="Enter new Todo" 
            />
            <button type="submit">Add</button>
        </form>
    );
};

3.3 Final App Structure

Finally, we will use TodoProvider in the App component to wrap the other components.

const App = () => {
    return (
        <TodoProvider>
            <h1>Todo List</h1>
            <AddTodo />
            <TodoList />
        </TodoProvider>
    );
};

4. State Management and Refactoring

State management is a crucial part of React applications. It helps clarify the flow and relationships of data later on. By using the Context API, child components can access the state directly for more efficient management.

4.1 State Management Patterns

There are various patterns for state management. When using it with the Context API, components must be designed to subscribe to it. This minimizes unnecessary re-renders.

4.2 Example of Refactoring

Refactoring allows for safely implementing additional features. For instance, let’s add logic to handle the completion status of Todo items.

const toggleTodo = (id) => {
    setTodos(todos.map(todo => todo.id === id ? { ...todo, completed: !todo.completed } : todo));
};

4.3 Visualizing Completed Todo Items

To visually represent completed Todo items, we will modify the TodoItem component.

const TodoItem = ({ todo, onRemove }) => {
    return (
        <li style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}>
            {todo.text}
            <button onClick={() => onRemove(todo.id)}>Delete</button>
        </li>
    );
};

5. Conclusion

In this tutorial, we learned how to use React’s Context API to supply data to the component tree and how to refactor a Todo application. Context makes it easy to share data between components and helps to keep the app’s structure cleaner.

Understanding state management and data flow using React will greatly aid in building complex applications in the future. Now, I encourage you to use the Context API to create various applications. Thank you!

React Course: Supplying Data to the Component Tree, Context

React is a JavaScript library used for building user interfaces (UIs) based on components. In this course, we will delve into how to use React’s Context API to supply data to the component tree. Context is one of React’s powerful features that helps in efficiently passing data between components.

1. What is Context API?

The Context API is a tool that allows data to be passed to components that do not require it in React. It is useful primarily for avoiding props drilling. By using Context, data can be transmitted without having to pass props directly from parent to child components.

Context is primarily useful for global state management or sharing data required by multiple child elements. For example, user authentication information, UI language settings, theme information, etc., can be managed using Context.

2. Components of Context API

The Context API consists of the following main components:

  • Creating Context: Use the React.createContext() function to create Context.
  • Provider Component: Use the Provider component of the Context to supply data to child components.
  • Consumer Component: This is the Consumer component for subscribing to data in child components. This technique uses the render props pattern.
  • Hooks: Use the useContext hook to utilize Context in functional components.

3. Creating and Using Context

Let’s first look at how to create Context. The following example explains how to create and use a simple Context:


import React, { createContext, useContext, useState } from 'react';

// 3.1. Creating Context
const MyContext = createContext();

// 3.2. Creating Provider component
const MyProvider = ({ children }) => {
    const [value, setValue] = useState('Hello, React!');

    return (
        
            {children}
        
    );
};

// 3.3. Example of using Consumer
const MyComponent = () => {
    const { value } = useContext(MyContext);
    return 

{value}

; }; // 3.4. App component const App = () => ( );

In this example, we create MyContext and supply data to child components through MyProvider. In MyComponent, we use the useContext hook to access the value of the Context.

4. Advanced Usage of React Context

When using the Context API, there are several considerations beyond the basic usage. In this section, we will discuss various strategies for using Context more effectively.

4.1. Using Multiple Contexts

It is possible to use multiple Contexts within a single application. Splitting different data into their respective Contexts makes the code cleaner and improves maintainability. For example, user settings, theme settings, and language settings can be managed in different Contexts.


const ThemeContext = createContext();
const LanguageContext = createContext();
            

4.2. Performance Optimization of Context

Using Context can potentially degrade performance. When Context changes, all child components re-render. To mitigate this, Context can be divided into finer-grained contexts or memoization can be used.


const MyComponent = React.memo(() => {
    const { value } = useContext(MyContext);
    return 

{value}

; });

4.3. Comparing Context and Redux

Both Context API and Redux are methods for global state management. However, Redux provides patterns for managing complex state along with additional features like middleware. For simple state management, the Context API is suitable, but as the application grows in complexity, considering Redux is advisable.

5. Practical Example with React

Now, let’s practice using the Context API. Below is a simple example that manages user authentication status.


const AuthContext = createContext();

const AuthProvider = ({ children }) => {
    const [isAuthenticated, setIsAuthenticated] = useState(false);

    const login = () => setIsAuthenticated(true);
    const logout = () => setIsAuthenticated(false);

    return (
        
            {children}
        
    );
};

const LoginButton = () => {
    const { login } = useContext(AuthContext);
    return ;
};

const LogoutButton = () => {
    const { logout } = useContext(AuthContext);
    return ;
};

const AuthStatus = () => {
    const { isAuthenticated } = useContext(AuthContext);
    return 

{isAuthenticated ? 'You are logged in' : 'Please log in'}

; }; const App = () => ( );

In the above example, we created AuthContext to manage user authentication status, and the related components provide login and logout functionality through Context.

6. Conclusion

The Context API is a powerful tool that helps in efficiently passing data between components in React. It can be utilized in a variety of scenarios, from simple data transmission to complex state management. By considering performance issues and using it appropriately, you can significantly improve development efficiency. I hope this course has been helpful for your React development journey.

React Course: Component

React is one of the most popular JavaScript libraries used to build modern user interfaces. React is designed to create reusable UI components, which is very useful for managing and maintaining complex structures in large applications. In this article, we will provide a deep understanding of React components by detailing the concept of components, types, how to create them, and practical examples.

1. What is a Component?

A component is a building block of the UI, a piece of code that is independently reusable. Each component can have its own state and lifecycle, and can be combined with other components to create complex UIs. Using components enhances code readability and maximizes reusability.

1.1 Advantages of Components

  • Reusability: Already written components can easily be reused in other projects or within the same project.
  • Modularity: Each component functions independently, making code maintenance easier.
  • Ease of Testing: Since each component operates independently, testing them individually is also convenient.

2. Types of Components

In React, components can mainly be divided into two types: class components and functional components.

2.1 Class Components

Class components are defined using the ES6 class syntax. They can have state and use lifecycle methods to control the component’s lifecycle.

import React, { Component } from 'react';

class MyClassComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  increment = () => {
    this.setState({ count: this.state.count + 1 });
  }

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.increment}>Increment</button>
      </div>
    );
  }
}

export default MyClassComponent;

2.2 Functional Components

Functional components are defined as simple JavaScript functions. After the introduction of React Hooks, functional components can also manage state.

import React, { useState } from 'react';

const MyFunctionalComponent = () => {
  const [count, setCount] = useState(0);

  const increment = () => {
    setCount(count + 1);
  };

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

export default MyFunctionalComponent;

3. Creating a Component

Creating a React component is not a difficult process. Below, we will look at the process of making components through basic examples of class and functional components.

3.1 Creating a Class Component

We will create a counter component named ‘Counter’.

import React, { Component } from 'react';

class Counter extends Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  increment = () => {
    this.setState({ count: this.state.count + 1 });
  }

  decrement = () => {
    this.setState({ count: this.state.count - 1 });
  }

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.increment}>Increment</button>
        <button onClick={this.decrement}>Decrement</button>
      </div>
    );
  }
}

export default Counter;

3.2 Creating a Functional Component

Below is a functional component named ‘Counter’ that has the same functionality.

import React, { useState } from 'react';

const Counter = () => {
  const [count, setCount] = useState(0);

  const increment = () => {
    setCount(count + 1);
  };

  const decrement = () => {
    setCount(count - 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
    </div>
  );
};

export default Counter;

4. Props and State

Components may appear similar, but each component shows significant differences in how it handles data. In this section, we will explain props and state in detail.

4.1 Props

Props are the means by which a parent component passes data to a child component. Props are read-only, so they cannot be directly modified within the component. The rendering result of the component changes based on the data passed from the parent component.

const Welcome = (props) => {
  return <h1>Hello, {props.name}</h1>;
};

const App = () => {
  return (
    <div>
      <Welcome name="Alice" />
      <Welcome name="Bob" />
    </div>
  );
};

4.2 State

State is the data managed within the component, representing dynamic data such as user input or the result of an API call. When the state is updated, React re-renders the component to update the UI.

import React, { useState } from 'react';

const Toggle = () => {
  const [isOn, setIsOn] = useState(false);

  const toggleSwitch = () => {
    setIsOn(!isOn);
  };

  return (
    <div>
      <p>Switch is {isOn ? 'On' : 'Off'}</p>
      <button onClick={toggleSwitch}>Toggle</button>
    </div>
  );
};

5. Component Lifecycle

The lifecycle of a React component can be divided into three main stages: mounting, updating, and unmounting. There are specific lifecycle methods called at each stage.

5.1 Mounting

This is the method called when a component is added to the DOM. Prominent examples include constructor and componentDidMount.

class MyComponent extends Component {
  constructor(props) {
    super(props);
    this.state = { data: null };
  }

  componentDidMount() {
    // Initial tasks like API calls
  }

  render() {
    return <div>My Component</div>;
  }
}

5.2 Updating

This is the method called when the component’s props or state change. componentDidUpdate is a key example.

componentDidUpdate(prevProps, prevState) {
  if (this.state.data !== prevState.data) {
    // Handle data change
  }
}

5.3 Unmounting

This is the componentWillUnmount method called when a component is removed from the DOM. It is primarily used to perform cleanup tasks.

componentWillUnmount() {
  // Cleanup like clearing timers
}

6. Advanced Component Patterns

In React, advanced component patterns can simplify the structure of complex UIs. Here are some advanced component patterns.

6.1 Higher-Order Components (HOC)

A HOC is a component that takes a component as an argument and returns a new component. This helps reduce code duplication and increases reusability.

const withLogging = (WrappedComponent) => {
  return class extends Component {
    componentDidMount() {
      console.log('Component mounted');
    }

    render() {
      return <WrappedComponent {...this.props} />;
    }
  };
};

6.2 Render Props

The Render Props pattern is a pattern in which a component passes a function as a prop to determine what to render. This helps separate data-processing logic from the UI.

class DataProvider extends Component {
  render() {
    return this.props.render(data);
  }
}

7. Conclusion

React components are a core component of modern web development, providing a powerful tool that facilitates reusability and maintainability. In this course, we learned the basic concepts of components, various types, how to create them, and advanced patterns. With this knowledge, we hope your React applications can advance even further.

If you would like more information about React components, please refer to the official documentation. Thank you!

React Course: Creating a Counter App Example

React is one of the most popular JavaScript libraries in modern web development. In this course, you will learn how to create a counter app using React. The counter app is a very simple project, but it is a great help in understanding and utilizing the basic concepts of React. The goals of this course are as follows:

  • Understand the basic concepts of React
  • Create and manage React components
  • Understand state and props
  • Implement event handling and state updates
  • Develop applications using React

1. Preparing the Project

Before starting this counter app project, let’s organize the necessary preparations. You need to set up the basic environment needed for development.

1.1. Setting Up the Development Environment

To use React, you first need to install Node.js and npm (Node Package Manager). Node.js provides the JavaScript runtime environment, and npm is the tool for package management.

  1. Download Node.js: Download the installer from the official Node.js website and install it.
  2. Check npm: After the installation is complete, check the installed versions of Node.js and npm with the following command:
  3. node -v
    npm -v

1.2. Creating a New React Project

To create a React project, we will use a tool called Create React App. This automatically configures the initial setup for a React app. Use the following command to create a new React project:

npx create-react-app counter-app

After entering the command above, a folder named counter-app will be created, and the basic template for a React application will be set up. After completion, navigate to that folder:

cd counter-app

1.3. Running the Development Server

After navigating to the project folder, you can run the development server with the following command:

npm start

When you enter this command, the React app will open in your default web browser at the address `http://localhost:3000`. Check if React is installed correctly through the initial screen.

2. Designing the Counter App

Now let’s briefly design the functionality and UI of the counter app. Essentially, this app allows users to increase or decrease the count by clicking a button.

2.1. Main Features

  • Button to increase the count
  • Button to decrease the count
  • Text displaying the current count
  • Ability to set the initial count value

2.2. UI Design

The UI of the counter app is simple. It basically includes two buttons and a text to display the state. We’ll design the components through a basic HTML structure.

3. Implementing the Counter App

Now let’s actually implement the counter app. Create a file named Counter.js inside the src folder and write the component.

3.1. Creating the Counter Component

import React, { useState } from 'react';

const Counter = () => {
    const [count, setCount] = useState(0);

    const increment = () => {
        setCount(count + 1);
    };

    const decrement = () => {
        setCount(count - 1);
    };

    return (
        

Current Count: {count}

); }; export default Counter;

The code above contains a React component with simple counter functionality. It uses the useState hook to manage the count state.

3.2. Adding the Counter Component to App.js

Now open the App.js file and add the Counter component. Modify the file as follows:

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

function App() {
    return (
        
); } export default App;

4. Adding Styling

Let’s add some styles to the counter app to make it look better. You can use a predefined CSS file or apply styles inline. Here we will use a CSS file for styling.

4.1. Creating the styles.css File

body {
    font-family: Arial, sans-serif;
    text-align: center;
}

button {
    margin: 10px;
    padding: 10px 15px;
    font-size: 16px;
}

4.2. Applying Styles

Now you can import and apply the styles in App.js:

import React from 'react';
import './styles.css'; // Import new CSS file
import Counter from './Counter';

function App() {
    return (
        
); } export default App;

5. Implementing Additional Features

The basic counter app is now complete. Next, let’s add the feature that allows users to set the initial count value.

5.1. Initial Count Setting Feature

const Counter = () => {
    const [count, setCount] = useState(0);
    const [inputValue, setInputValue] = useState('');

    const increment = () => {
        setCount(count + 1);
    };

    const decrement = () => {
        setCount(count - 1);
    };

    const setInitialCount = (e) => {
        e.preventDefault();
        setCount(Number(inputValue));
        setInputValue('');
    };

    return (
        

Current Count: {count}

); };

In the code above, the inputValue state was added to allow the user to input a number. A button to set the initial value was added, and it applies the value to the count when clicked.

6. Conclusion and Deployment

The implementation of the counter app is complete. Now, we are ready to deploy the application. There are two basic methods: GitHub Pages and Vercel.

6.1. Deploying with GitHub Pages

  1. Push the project to GitHub.
  2. Build the project with the following command:
  3. npm run build
  4. Host the generated build folder on GitHub Pages.

6.2. Deploying with Vercel

  1. Sign up for Vercel and link your GitHub repository.
  2. Vercel will automatically deploy the project.

Conclusion

Through this course, you have learned the basic concepts of React and implemented a counter app. I hope this process has helped you understand state management, component creation, and event handling in React. Challenge yourself with more complex projects to improve your React skills!

If you found this article useful, subscribe to the blog and check out other courses!

React Course: Creating a Counter App Example

React is one of the most widely used JavaScript libraries for building UIs. In this tutorial, we will learn how to create a simple counter app using React. This app will be based on basic state management, event handling, and React’s component-based architecture.

1. Project Setup

First, let’s start a React project using create-react-app. This tool helps to easily set up a React app. Run the command below to create a React project.

        npx create-react-app counter-app
    

Once the project is created, navigate to the generated directory.

        cd counter-app
    

2. Creating the Counter Component

Now, let’s create a counter component. Create a file named Counter.js inside the src folder and write the following code.

        import React, { useState } from 'react';

const Counter = () => {
    const [count, setCount] = useState(0);

    const increment = () => {
        setCount(count + 1);
    };

    const decrement = () => {
        setCount(count - 1);
    };

    return (
        

Count: {count}

); }; export default Counter;

3. Adding the Counter Component

Now, let’s add this counter component to the main App.js file. Open the src/App.js file and modify it as follows.

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

function App() {
    return (
        

React Counter App

); } export default App;

4. Running the App

All code changes are complete, so we run the app with the following command.

        npm start
    

Open http://localhost:3000 in your web browser to see the basic counter app.

5. Adding Features

Now, let’s implement some additional features in the counter app. For example, we can add a button to reset the count and functionality to set maximum and minimum values.

5.1. Adding a Reset Button

Let’s add a reset button to the counter component. Modify the code as follows.

        const reset = () => {
        setCount(0);
    };

    return (
        

Count: {count}

);

5.2. Limiting Maximum and Minimum Values

Now, let’s ensure that the count does not exceed maximum and minimum values. Modify the code as follows.

        const MAX_COUNT = 10;
const MIN_COUNT = 0;

const increment = () => {
    if (count < MAX_COUNT) {
        setCount(count + 1);
    }
};

const decrement = () => {
    if (count > MIN_COUNT) {
        setCount(count - 1);
    }
};
    

6. Efficiency of State Management

There are several ways to manage state in React. For simple cases like this app, the useState hook is appropriate. However, as the application grows or state management becomes more complex, consider using external state management libraries like Context API or Redux.

7. Conclusion

In this tutorial, we created a simple counter app using React. We learned about basic state management, event handling, and component-based architecture. Based on these fundamentals, we are now ready to develop more complex applications.

8. Next Steps

Try expanding your counter app by implementing more features or improving the design. Leveraging the various capabilities of React allows you to develop much more complex and attractive applications. In the next tutorial, we will learn how to create a multi-page application using React Router.

I hope this tutorial was helpful! If you have any questions or feedback, please leave a comment!