
Security News
Node.js Drops Bug Bounty Rewards After Funding Dries Up
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.
react-ghost
Advanced tools
react-ghost is a specialized npm library inspired by the anime aesthetic, specifically designed for React application development. It mirrors the concept of "Ghost in the Shell," aiming to incorporate a ghostly essence into the React ecosystem. The library focuses on managing the business logic layer within React applications, offering a structured way to connect UI components with their underlying logic. Through its distinct approach, react-ghost facilitates the separation of the logic layer from the UI layer, enabling developers to maintain cleaner and more organized codebases.
npm i react-ghost
react-ghost integrates smoothly into your React application, allowing you to utilize React's hooks and Redux's capabilities within the framework of react-ghost. By leveraging this library, you can encapsulate business logic within "ghosts" without altering the way you use React hooks in your components. This means all standard React hooks (useState, useEffect, useContext, useSelector, useDispatch, etc.) and any custom hooks you've created remain applicable within the context of react-ghost.
Usually we use jsx for UI Components:
const Component = () => <div>
<MenuTop /> /* connect to MenuGhost */
<Pagination /> /* connect to ListGhost */
<List /> /* connect to ListGhost */
<ItemHeader /> /* connect to ItemGhost */
<ItemContent /> /* connect to ItemGhost */
<Pagination /> /* connect to ListGhost */
<MenuBottom /> /* connect to MenuGhost */
</div>
But for separate logic layer from UI layer we need some other namings.
So I came up with two functions: ghost() and ghosts()
import { ghosts, ghost } from 'react-ghost';
const PageGhost = ({ param1, param2, id }) => ghosts(
ghost(MenuGhost, { param1 }),
ghost(ListGhost, { param2 }),
id && ghost(ItemGhost, { id }),
)
Its equals to react createElement:
import { createElement, Fragment } from 'react';
const ghost = createElement;
const ghosts = (...children) => createElement(Fragment, null, ...children);
export { ghost, ghosts };
That is all content of this library. So you can use all features of React library for code Business logic.
For more information read this article: Put a Soul into a React-Redux Project
This architecture leverages:
business logic (Ghost) <------> state (Redux) <------> UI (React)
import {useSelector, useMemo } from 'react';
import { useDispatch } from 'react-redux'
import { ghosts, ghost } from 'react-ghost';
const PagesGhost = () => {
const url = useSelector(({ history }) => history.url)
const pageGhost = useMemo(() => getPageGhostByUrl(url), [url])
return ghost(pageGhost)
}
const HomePageGhost = () => {
const dispatch = useDispatch()
useEffect(() => {
const interval = setInterval(() => {
dispatch({type: 'COUNTER_PLUS'})
}, 1000)
return () => clearInterval(interval)
})
// you should explicitly point that this ghost hasn't child ghosts
return null
}
Use jest and helper functions from react-ghost-test for write tests For example:
import { waitForState, checkDispatch } from 'react-ghost-test'
import { ghost } from 'react-ghost';
describe('init', () => {
test('create app actor', async () => {
// Create redux context provider
// and insert into this provider Application actor.
// After that verify store contains 'main' reducer.
await waitForState(
() => create(ghost(
Provider,
{ store },
ghost(AppActor),
)),
[
(state) => expect(state).toHaveProperty('main'),
],
);
});
// Dispatch action 'boot'.
// AppActor should subscribe to this action and do some
// work for boot/reboot application.
// At first we wait while booting flag set to true.
// After booting ('booing' flag equals to false) we verify
// state in the store
// And theard - verify that we redirect to home page
test('boot', async () => {
await checkDispatch(
mainActions.boot('main'),
[
(state) => state.toHaveProperty('main.booting', true),
(state) => state.toMatchObject({
main: {
booted: true,
booting: false,
},
history: {
location: { pathname: '/' },
},
}),
(state) => state.toMatchObject({
homePage: {
title: 'Home Page',
},
}),
],
);
});
// Redirect to books page
// History Actor should check histor.toUrl variable.
// If it changed then History actor should navigate to this page.
// So we asssert history.loacation variable
// Pages Actor should subscribe to history.loacation and
// attach specific actor for this location - BoocksActor
// We verify this by check 'booksPage' reducer in the store
// Also we save current state in temporary variable for restore
// in another test
test('open books page', async () => {
await checkDispatch(
historyActions.push('history', '/books'),
[
(state) => state.toMatchObject({ history: {
toUrl: '/books',
action: 'push'
} }),
(state) => state.toMatchObject({
history: {
location: { pathname: '/books' },
},
}),
(state) => {
state.not.toHaveProperty('homePage');
state.toMatchObject({
booksPage: {
list: [],
},
});
// save state for restore in another test
savedStates.booksPage = store.getState();
},
],
);
});
});
So we tested logic of application. After business logic implemented, you can add thin layer of UI using react components.
Support all react versions from 16 and later
FAQs
react-ghost - it is logic/biseness layer, actors and workers
We found that react-ghost demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.

Security News
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.