Eventrix https://eventrix.io React and React Native State Management Library Sun, 18 Dec 2022 21:23:39 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.4 Redux and Eventrix performance tests https://eventrix.io/redux-and-eventrix-performance-tests/ https://eventrix.io/redux-and-eventrix-performance-tests/#respond Sun, 18 Dec 2022 20:32:00 +0000 https://eventrix.io/?p=835

We have prepared a sample react application that allows us to perform performance tests of the Redux and Eventrix state management libraries.
The simulation can be performed using the following links:

Eventrix Messenger App

Redux Messenger App

Source codes can be downloaded here:
Eventrix Performance Tests

The results of the activities carried out are presented in the chart:

eventrix-vs-redux

See how both libraries work

]]>
https://eventrix.io/redux-and-eventrix-performance-tests/feed/ 0
How to manage state in React with Eventrix https://eventrix.io/how-to-manage-state-in-react-with-eventrix/ https://eventrix.io/how-to-manage-state-in-react-with-eventrix/#respond Tue, 13 Dec 2022 12:15:03 +0000 https://eventrix.io/www/?p=771 In this article, I will show you how to easily manage a global state using Eventrix. I will write a “to-do app” as an example application. You can find the full application example here.

Installation

Of course, as with any library, you need to install it and write a few lines of code to be able to use it.

npm install eventrix — save

Project configuration

After installation, create a file in which we’ll initiate the Eventrix instance.

import { Eventrix } from "eventrix";
import taskEventsReceivers from "./tasks";

const initialState = {
    tasks: []
};

export default new Eventrix(initialState, taskEventsReceivers);

Eventrix takes the initial state of our application as the first argument and the list of receivers as the second argument. I’ll explain what a receiver is and how to use it later on.

As we have already defined the instance and created the default global state of our application, the last step is to use Provider. It is responsible for passing the context of our Eventrix instance to all components where it will be needed.

import React from "react";
import { EventrixProvider } from "eventrix";

import eventrix from "./eventrix";
import TodoList from "./TodoList";
import CreateTaskForm from "./CreateTaskForm";
import TodoFooter from "./TodoFooter";
import "./styles.css";

export default function App() {
    return (
        <EventrixProvider eventrix={eventrix}>
            <div className="App">
                <h1>TO DO LIST</h1>
                <div className="todo-app">
                    <CreateTaskForm />
                    <TodoList />
                    <TodoFooter />
                </div>
            </div>
        </EventrixProvider>
    );
}

Provider works pretty much the same way as in other state management libraries. It takes props from an Eventrix instance that will be used in application components.

Use of state in a list component

Now that we have everything configured, we can start using the state in our components, for this we use the useEventrixState Hook. As an example, let’s create a task list and a filter.

import React from "react";
import { useEventrixState } from "eventrix";

import Task from "./Task";
import "./TodoList.css";

const TodoList = () => {
    const [tasks] = useEventrixState("tasks");
    const [statusFilter, setStatusFilter] = useEventrixState("filter.status");
    
    const tasksList = statusFilter ? tasks.filter((task) => task.status === statusFilter) : tasks;
    
    return (
        <div>
            <div className="filters">
                <div
                    className={`status-button ${!statusFilter ? "active" : ""}`}
                    onClick={() => setStatusFilter("")}
                >
                    All
                </div>
                <div
                    className={`status-button ${statusFilter === "todo" ? "active" : ""}`}
                    onClick={() => setStatusFilter("todo")}
                >
                    Todo
                </div>
                <div
                    className={`status-button ${statusFilter === "done" ? "active" : ""}`}
                    onClick={() => setStatusFilter("done")}
                >
                    Done
                </div>
            </div>
            <div className="list">
                {tasksList.length === 0 && (
                    <div className="list-placeholder">Tasks list empty</div>
                )}
                {tasksList.map((task) => (
                    <Task key={task.id} task={task} />
                ))}
            </div>
        </div>
    );
};

export default TodoList;

Hook takes as the first attribute the path to the state of interest. If the state does not exist, it is okay, we will then get “undefined” and if we set some state, the path will be automatically created. Hook also causes automatic re-rendering of the component if the value of the state indicated by us changes. It is very important to give the path exactly to the value we are going to use. Eventrix uses accurate paths to analyze which components will be reloaded when changing the state.

As you can see, we’ve added “filters.status” path to the “status” filter. This means that we take the “status” value from the “filters” object in the state.

const [
statusFilter,
setStatusFilter
] = useEventrixState(“filter.status”);

By specifying the exact path, we guarantee that the component will only reload when someone modifies the entire “filter” object or changes the value of “filter.status” in the object. If someone changes a different value of a filter, the component will not be reloaded because these changes are not important for this component. Hook works similarly to useState but only uses the global state and does not default to the initial state value, which is defined in the initial state of the application. If you don’t set an initial value then you can use the default value.

Calling up a task adding event

Eventrix, instead of operating on actions, operates on its own events. Components and other elements of the application have the ability to emit and listen to events.

Let’s implement the task adding form where we will need to emit an event in order to add a task to the list using the useEmit hook.

Hook takes the name of the event that will be emitted as the first attribute. The data to be delivered with the event is transferred as the second attribute. This event will be delivered to all elements that are listening to it. We currently do not have any registered items using the “CREATE_TASK_EVENT_NAME” event yet. Of course, to be precise, the name of the event is a string.

const CREATE_TASK_EVENT_NAME = ‘tasks:create’;

Receiving events and set value to the state

If we want to receive an event and modify the state based on it, we use EventsReceiver. It is responsible for receiving events and modifying the state of the application synchronously or asynchronously. So let’s create a receiver that will be responsible for adding a task to the task list.

import { EventsReceiver } from "eventrix";

export const CREATE_TASK_EVENT_NAME = "tasks:create";

const createTaskReceiver = new EventsReceiver(
    CREATE_TASK_EVENT_NAME,
    (eventName, { task }, stateManager) => {
        const tasks = stateManager.getState("tasks");
        stateManager.setState("tasks", [task, ...tasks]);
    }
);

export default [
    createTaskReceiver,
];

EventsReceiver takes the name of the event or an array of event names to which it will be listening as the first argument. The second argument is the event handler, i.e. the function that will handle the event. In the attributes, this function will receive the name of the event, the data that is sent with the event and the stateManager. StateManager is responsible for state management in the application. You can use it to get and set any state. Of course, we can also specify the state path as in the useEventrixState hook. We provide the path in the case of getting (getState) and setting (setState) the state value.

As I mentioned before, you can modify the state of the application synchronously and asynchronously. The example above shows how this can be done synchronously. If we want to make a request to the API asynchronously and then add the task to the list, we can do it as follows.

import { EventsReceiver } from "eventrix";
import axios from “axios”;

export const CREATE_TASK_EVENT_NAME = "tasks:create";

const createTaskReceiver = new EventsReceiver(
    CREATE_TASK_EVENT_NAME,
    (eventName, { task }, stateManager) => {
        return axios.post('/tasks', { task }).then(({ data }) => {
            const tasks = stateManager.getState('tasks');
            stateManager.setState('tasks', [data, ...tasks]);
        });    
    }
);

export default [
    createTaskReceiver,
];

Adding support for other events

We already have a form and a to-do list. Now we are going to add other events that will allow us to remove tasks and change their status. For this purpose, we create a “Task” component that will emit events.

import React from "react";
import { useEmit } from "eventrix";
import {
    MARK_TASK_AS_DONE_EVENT_NAME,
    MARK_TASK_AS_TODO_EVENT_NAME,
    REMOVE_TASK_EVENT_NAME
} from "./eventrix/tasks";

const Task = ({ task }) => {
    const emit = useEmit();
    return (
        <div className="list-item">
            <input
                type="checkbox"
                checked={task.status === "done"}
                onChange={() =>
                    emit(
                        task.status === "todo"
                            ? MARK_TASK_AS_DONE_EVENT_NAME
                            : MARK_TASK_AS_TODO_EVENT_NAME,
                        { id: task.id }
                    )
                }
            />
            <div className="task-title">{task.title}</div>
            <div className={`status ${task.status}`}>{task.status}</div>
            <button
                onClick={() => emit(REMOVE_TASK_EVENT_NAME, { id: task.id })}
                className="removeButton"
            >
                X
            </button>
        </div>
    );
};

export default Task;

The task component emits all the events we need. We can now add receivers that will modify the state of our application.

import findIndex from "lodash/findIndex";
import { EventsReceiver } from "eventrix";

export const CREATE_TASK_EVENT_NAME = "tasks:create";
export const REMOVE_TASK_EVENT_NAME = "tasks:remove";
export const MARK_TASK_AS_DONE_EVENT_NAME = "tasks:markAsDone";
export const MARK_TASK_AS_TODO_EVENT_NAME = "tasks:markAsTodo";

const createTaskReceiver = new EventsReceiver(
    CREATE_TASK_EVENT_NAME,
    (eventName, { task }, stateManager) => {
        const tasks = stateManager.getState("tasks");
        stateManager.setState("tasks", [task, ...tasks]);
    }
);

const removeTaskReceiver = new EventsReceiver(
    REMOVE_TASK_EVENT_NAME,
    (eventName, { id }, stateManager) => {
        const tasks = stateManager.getState("tasks");
        const newTasks = tasks.filter((task) => task.id !== id);
        stateManager.setState("tasks", newTasks);
    }
);

const markAsDoneReceiver = new EventsReceiver(
    MARK_TASK_AS_DONE_EVENT_NAME,
    (eventName, { id }, stateManager) => {
        const tasks = stateManager.getState("tasks");
        const taskIndex = findIndex(tasks, (task) => task.id === id);
        const task = { ...tasks[taskIndex], status: "done" };
        stateManager.setState(`tasks.${taskIndex}`, task);
    }
);

const markAsTodoReceiver = new EventsReceiver(
    MARK_TASK_AS_TODO_EVENT_NAME,
    (eventName, { id }, stateManager) => {
        const tasks = stateManager.getState("tasks");
        const taskIndex = findIndex(tasks, (task) => task.id === id);
        const task = { ...tasks[taskIndex], status: "todo" };
        stateManager.setState(`tasks.${taskIndex}`, task);
    }
);

export default [
    markAsDoneReceiver,
    markAsTodoReceiver,
    createTaskReceiver,
    removeTaskReceiver
];

The receivers that we have added are transferred to the Eventrix instance when it is created (project configuration step). We can also add receivers dynamically while the application is running using the eventrix.useReceiver function and remove it using eventrix.removeReceiver.

Architecture of Eventrix

Eventrix library architecture state management react

Devtools

Eventrix also has development tools with the following functionalities:

  • preview state
  • view the history of state changes
  • event history preview
  • view statistics of the number of items listening per each state
  • view statistics of the number of state changes
  • view statistics of the number of events emitted

These tools significantly facilitate application optimization and condition analysis. So far, these tools are available for the Chrome browser here.

Conclusion

Eventrix is ​​a state management library that doesn’t require us to write a lot of code. The big plus is efficiency, flexibility and scalability. What I mean here is the fact that the number of elements connected to Eventrix or states does not affect the performance of the application. Eventrix, apart from condition management, gives us the ability to communicate between components through events. It is a kind of message broker on the frontend.

The library is new, and it does not have a large community yet, but it has RST Software behind it, a software development company that helps both startups and large enterprises to build their applications based on micro-services (such as, among other, Trans.eu), which guarantees it will be maintained and developed. I really recommend you give it a try in one of your projects and feel free to submit your feedback either in the comments below or on our GitHub.

]]>
https://eventrix.io/how-to-manage-state-in-react-with-eventrix/feed/ 0
Painless alert management in React https://eventrix.io/painless-alert-management-in-react/ https://eventrix.io/painless-alert-management-in-react/#respond Tue, 13 Dec 2022 08:45:19 +0000 https://eventrix.io/www/?p=734 react material ui alerts example with state management

Managing alerts in React can be effortless when the right technologies are utilized. Selecting Eventrix and MUI is a good example. Thanks to using them, alerts can be managed effortlessly.

MUI gives the developer an opportunity to display well designed alert messages. When using Eventrix, developers can communicate between a component using the MUI alerts component and the place where they want to call an alert. Take a look at an example below of how to use Eventrix with MUI.

Eventrix with MUI

import { useEvent } from "eventrix";
import { useState } from "react";
import Stack from "@mui/material/Stack";
import Alert from "@mui/material/Alert";

const Alerts = () => {
    const [alerts, setAlerts] = useState([]);
    useEvent("Alerts:show.success", (message) => {
        const id = new Date().getTime();
        setAlerts([{ message, type: 'success', id }, ...alerts]);
    });
    
    return (
        <Stack spacing={2}>
            {alerts.map(({ message, type, id }) => (
                <Alert key={id} severity={type}>{message}</Alert>
            ))}
        </Stack>
    );
}

export default Alerts;
vie

 

This example shows how to listen to success messages.

import React from "react";
import { useEmit } from "eventrix";
import Button from "@mui/material/Button";

const AlertButton = () => {
    const emit = useEmit();
    return (
        <Button
            variant="contained"
            onClick={() => {
                emit("Alerts:show.success", "Success message");
            }}
        >
            Show success alert
        </Button>
    )
}

export default AlertButton;

 

Here is an example of how to display alerts from any place of the application.

You can see the full implementation here. The example contains all kind of messages and alert auto removal functionality.

Conclusion

Usually developers need to display alerts in many different places of an application and they don’t want to use the same code repeatedly. Instead, Eventrix could be applied to communicate with alert components that display the alert message. Thanks to that you can write less code, and achieve the same result. On top of that, this functionality can be reusable in other places.

]]>
https://eventrix.io/painless-alert-management-in-react/feed/ 0
Handle requests with Eventrix https://eventrix.io/handle-requests-with-eventrix/ https://eventrix.io/handle-requests-with-eventrix/#respond Tue, 13 Dec 2022 08:42:45 +0000 https://eventrix.io/www/?p=730 Sometime we need to abort last requests and call new one when we change route before requests finished. For this purpose you can use RequestsHandler from eventrix library. RequestsHandler gives you possibility to abort all of requests that you don’t need anymore.

Handle requests with Eventrix - state management library for react
Below we have example of simple request.

import axios from 'axios';

const getUsersList = () => {
    return axios.get('https://abc.com/users').then(({ data }) => {
        return data;
    }),
}

export default getUsersList;

Easy way to abort pending requests

We can have situation when we want to cancel last users GET request before call new one. For this purpose we can use code below.

import { RequestsHandler, Eventrix } from 'eventrix';
import axios from 'axios';

const eventrix = new Eventrix({}, []);
const requestsHandler = new RequestsHandler(eventrix);

const getUsersList = () => {
    const requestId = 'getUsers';
    requestsHandler.abortAllById(requestId);
    return requestsHandler.handleRequest(axios.get('https://abc.com/users'), requestId).then(({ data }) => {
        return data;
    }),
}

export default getUsersList;

As we can see above, request is handled by RequestsHandler instance and we can abort all of requests with id “getUsers”. Of course RequestsHandler have more methods and we can abort all requests or resolve them with data what we expect.

Conclusion

Eventrix is library to manage global state of web and mobile applications based on React but has many cool features that give you easy way to resolve difficult problems. Thanks for reading and give me know what do you think about it.

]]>
https://eventrix.io/handle-requests-with-eventrix/feed/ 0