Share
Explore

React Lab: Handling REACT JSX front end components

Creating and deploying a React component to an HTML page involves writing the React component in JSX and then rendering it within a specific DOM element, typically the one with the id="root".
I'll show you how to create a simple Greeting component that accepts a name prop and how you can deploy it to an HTML page.
Firstly, let's create the React component (Greeting.js):
import React from 'react';

// Greeting component accepts a 'name' prop
const Greeting = (props) => {
return <h1>Hello, {props.name}!</h1>;
};

export default Greeting;

Next, we will use this Greeting component inside our main App.js file, which is the entry point for a React application.
App.js:
import React from 'react';
import ReactDOM from 'react-dom';
import Greeting from './Greeting';

const App = () => {
const userName = 'Alice';

return (
<div>
{/* Using the Greeting component and passing 'name' prop */}
<Greeting name={userName} />
</div>
);
};

// Render the App component into the DOM element with the id 'root'
ReactDOM.render(<App />, document.getElementById('root'));
Now, let's see the corresponding HTML page (index.html), which includes the div with the id="root" where the React application will be mounted.
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>React Component Example</title>
</head>
<body>
<!-- This is the root element where our React app will be mounted -->
<div id="root"></div>

<!-- Scripts to include React, ReactDOM, and our compiled application -->
<script src="path/to/react.js"></script>
<script src="path/to/react-dom.js"></script>
<script src="path/to/compiled_app.js"></script>
</body>
</html>
In this example, compiled_app.js would be the bundled JavaScript file that webpack (or another module bundler) creates from your JSX code. This file includes the React component code that gets executed in the browser.
By rendering the App component using ReactDOM.render and targeting the DOM element with id="root", the Greeting component's HTML output is injected into that element.
The Greeting component is functionally equivalent to an HTML tag, in that it generates a piece of the DOM structure that is displayed on the page:
<h1>Hello, Alice!</h1>
This will be the actual output inside the root div of the HTML page, effectively displaying the greeting message with the passed-in name, similar to how an <img> tag would display an image:
<img src='dog.gif'/>
This illustrates how React components and HTML tags can be used interchangeably in the sense that they both produce HTML output to be displayed on the page.
However, React components are more powerful, as they can contain logic, state, and a variety of behavior, which HTML tags alone cannot.

What about passing in the prop from the HTML Page?

Using data-* attributes on a DOM element and a script to manually instantiate a React component, you can indirectly pass information from the HTML to a React component during initialization.
Here's how you can achieve this:
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>React Component Example</title>
</head>
<body>
<!-- 'data-name' attribute holds the value we want to pass as a prop -->
<div id="root" data-name="Alice"></div>

<!-- Scripts to include React, ReactDOM, and our compiled application -->
<script src="path/to/react.js"></script>
<script src="path/to/react-dom.js"></script>
<!-- Ensure your React component script comes after React and ReactDOM -->
<script src="path/to/your_component_bundle.js"></script>
<script>
// Extract value from 'data-name' attribute and pass as a prop to React component
const domContainer = document.querySelector('#root');
const userName = domContainer.getAttribute('data-name');
ReactDOM.render(React.createElement(Greeting, { name: userName }), domContainer);
</script>
</body>
</html>
In the example above, the data-name attribute of the root div holds the userName we want to pass into our Greeting component.
The script at the bottom of your HTML file is crucial as it:
Selects the DOM element where the React app will mount (the element with id="root").
Extracts the value from the data-name attribute.
Uses ReactDOM.render to render the Greeting component, creating it via React.createElement and passing the extracted value as props.
Note: This approach is mixing imperative DOM manipulation with React's declarative paradigm, which is not a usual practice when developing React applications.
Typically, you would manage state and props within the React ecosystem itself, perhaps using something like Context or a state management library to pass down props.
This example is mostly instructional and is not the best practice for standard React application development.
For dynamic data handling, consider using state management libraries like:
Redux
Context API
React state hooks along with backend API calls.


A simple example illustrating Redux


To illustrate a simple example of Redux, we'll create a small React app with Redux that manages a counter. Our app will have the ability to increment and decrement the counter value.
Firstly, make sure Redux and React-Redux are installed:
npm install redux react-redux
Now, let's start by creating the Redux parts:
actions/counterActions.js:
// Action Types
export const INCREMENT = 'INCREMENT';
export const DECREMENT = 'DECREMENT';

// Action Creators
export const incrementCounter = () => ({
type: INCREMENT,
});

export const decrementCounter = () => ({
type: DECREMENT,
});
reducers/counterReducer.js:
import { INCREMENT, DECREMENT } from '../actions/counterActions';

const initialState = {
count: 0,
};

// Counter Reducer
const counterReducer = (state = initialState, action) => {
switch (action.type) {
case INCREMENT:
return { ...state, count: state.count + 1 };
case DECREMENT:
return { ...state, count: state.count - 1 };
default:
return state;
}
};

export default counterReducer;
store.js:
import { createStore } from 'redux';
import counterReducer from './reducers/counterReducer';

// Create Store
const store = createStore(
counterReducer,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() // Enables Redux DevTools
);

export default store;
Next, we set up the React component that uses the Redux store:
CounterComponent.js:
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { incrementCounter, decrementCounter } from './actions/counterActions';

const CounterComponent = () => {
// Access Redux state and dispatch
const count = useSelector(state => state.count);
const dispatch = useDispatch();

return (
<div>
<h1>Counter: {count}</h1>
<button onClick={() => dispatch(incrementCounter())}>Increment</button>
<button onClick={() => dispatch(decrementCounter())}>Decrement</button>
</div>
);
};

export default CounterComponent;
Finally, we wrap our app with the Redux provider in the entry point:
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import store from './store';
import CounterComponent from './CounterComponent';

ReactDOM.render(
<Provider store={store}>
<CounterComponent />
</Provider>,
document.getElementById('root')
);
What we have here is:
Action types and creators define the actions that can be taken on the store.
The reducer, counterReducer, specifies how the state changes in response to the actions.
The Redux store is created with createStore() and includes the reducer.
The React CounterComponent uses useSelector to read from the Redux state and useDispatch to dispatch actions.
The Provider from React-Redux wraps the app component and passes the store down to all components.
With this setup, clicking the "Increment" and "Decrement" buttons will dispatch actions that update the Redux state, and the displayed counter will update reactively.
This illustrates a basic Redux flow with React.

Context API

The Context API is a React feature that provides a way to pass data through the component tree without having to pass props down manually at every level. Here's a simple example of how to use the Context API to create a theme toggler within a React app.

First, let's set up the context provider:
ThemeContext.js:
import React, { createContext, useState } from 'react';

// Create the context
const ThemeContext = createContext();

// Provider component that wraps your app and provides the theme state
export const ThemeProvider = ({ children }) => {
const [theme, setTheme] = useState('light'); // Default theme is light

// Toggle the theme
const toggleTheme = () => {
setTheme(theme === 'light' ? 'dark' : 'light');
};

// The value that will be given to the context
const contextValue = {
theme,
toggleTheme,
};

return (
<ThemeContext.Provider value={contextValue}>
{children}
</ThemeContext.Provider>
);
};

export default ThemeContext;
In this file, we created a ThemeContext with two values: theme and toggleTheme. A ThemeProvider component is defined, that provides the theme context to its children components.
Next, let's create a component that uses the context:
ToggleButton.js:
import React, { useContext } from 'react';
import ThemeContext from './ThemeContext';

const ToggleButton = () => {
// Use the context
const { theme, toggleTheme } = useContext(ThemeContext);

return (
<button onClick={toggleTheme}>
Switch to {theme === 'light' ? 'dark' : 'light'} theme
</button>
);
};

export default ToggleButton;
In this component, we use useContext to access the ThemeContext values. Then we render a button that, when clicked, will call the toggleTheme function from our context.
Let's include our context in our main App component:
App.js:
import React from 'react';
import { ThemeProvider } from './ThemeContext';
import ToggleButton from './ToggleButton';

const App = () => {
return (
<ThemeProvider>
<div>
<h1>Context API Example</h1>
<ToggleButton />
</div>
</ThemeProvider>
);
};

export default App;
Here, the ThemeProvider wraps the part of the app where we want the theme context to be available. Inside the provider, we render a ToggleButton.
Finally, we mount our App component to the DOM:
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));
This example demonstrates how to use the Context API to manage and share state without prop drilling. By wrapping a portion of the app with the ThemeProvider, we could access the theme context from anywhere within this provider. In larger applications, you might use the Context API to manage things like user authentication, language preferences, and more global states.

Using state hooks with backend API calls:

In this example, we'll create a simple React application that uses the useState and useEffect hooks to fetch data from a backend API and display it. We'll assume our backend API returns a list of users.
First, we need to have a list of users available through a backend API, which could be a RESTful service endpoint. For the sake of simplicity, we will use https://jsonplaceholder.typicode.com/users for fetching mock user data.
Here's a React component that fetches and displays this user data:
UsersList.js:
import React, { useState, useEffect } from 'react';
import axios from 'axios'; // Axios for making HTTP requests

const UsersList = () => {
const [users, setUsers] = useState([]); // Initial state is an empty array
const [loading, setLoading] = useState(true); // Manage loading state
const [error, setError] = useState(null); // Store any error during fetch

useEffect(() => {
// Function to fetch users
const fetchUsers = async () => {
try {
setLoading(true);
const response = await axios.get('https://jsonplaceholder.typicode.com/users');
setUsers(response.data); // Update the users state
setLoading(false);
} catch (error) {
setError(error);
setLoading(false);
}
};
fetchUsers();
}, []); // The empty array means it runs once on component mount

if (loading) return <p>Loading users...</p>;
if (error) return <p>Error loading users!</p>;

return (
<div>
<h1>Users List</h1>
<ul>
{users.map(user => (
<li key={user.id}>
{user.name} - {user.email}
</li>
))}
</ul>
</div>
);
};

export default UsersList;
Then, we include this component inside our main App.js component:
App.js:
import React from 'react';
import UsersList from './UsersList';

const App = () => {
return (
<div>
<UsersList />
</div>
);
};

export default App;
Lastly, index.js renders the App:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import axios from 'axios';

// Set up global configuration for axios if needed
axios.defaults.headers.common['Authorization'] = 'Bearer your_auth_token';

ReactDOM.render(<App />, document.getElementById('root'));
In this example, the UsersList component:
Initializes users state to hold the list of users.
Initializes loading state to indicate whether it's currently fetching data.
Initializes error state to capture any error that might occur while fetching the data.
Uses useEffect to fetch user data from the API when the component mounts.
If loading is true, displays a loading message.
Once the data is fetched, maps over the users array and renders an unordered list with their details.
We're using axios for making the HTTP request, which is a popular promise-based HTTP client. Remember, in a real-world application, you'd use environment variables and proper authentication mechanisms when dealing with APIs.
Error handling is minimal in this example for simplicity, but in a production app, you'd want more comprehensive error checking and user feedback.

Want to print your doc?
This is not the way.
Try clicking the ⋯ next to your doc name or using a keyboard shortcut (
CtrlP
) instead.