Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Thoughts for 2.0 #171

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 0 additions & 40 deletions .circleci/config.yml

This file was deleted.

14 changes: 0 additions & 14 deletions .eslintrc

This file was deleted.

18 changes: 10 additions & 8 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
---
name: Bug report
about: Create a report to help us improve

---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:

1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
Expand All @@ -21,15 +21,17 @@ A clear and concise description of what you expected to happen.
If applicable, add screenshots to help explain your problem.

**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]

- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]

**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]

- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]

**Additional context**
Add any other context about the problem here.
1 change: 0 additions & 1 deletion .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
---
name: Feature request
about: Suggest an idea for this project

---

**Is your feature request related to a problem? Please describe.**
Expand Down
30 changes: 30 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: main

on:
push:
branches: [master]
pull_request:
branches: [master]

jobs:
build:
runs-on: ubuntu-latest

strategy:
matrix:
node-version: [12.x, 14.x]

steps:
- uses: actions/checkout@v2

- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}

- run: yarn
- run: yarn prettier --ignore-path .gitignore --check .

- run: yarn build
# Need tests plz
# - run: yarn workspace @mckayla/electron-redux-e2e test
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.parcel-cache
dist/
node_modules/
coverage/
Expand Down
1 change: 0 additions & 1 deletion .yarnrc

This file was deleted.

3 changes: 3 additions & 0 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Code of Conduct

Contributors should follow the [Rust Code of Conduct](https://www.rust-lang.org/conduct.html).
2 changes: 1 addition & 1 deletion packages/electron-redux/LICENSE.md → LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2016 Burkhard Reffeling
Copyright (c) 2020 McKayla Washburn, Burkhard Reffeling

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
21 changes: 0 additions & 21 deletions LICENSE.md

This file was deleted.

185 changes: 42 additions & 143 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,173 +1,72 @@
# electron-redux

[![CircleCI](https://circleci.com/gh/hardchor/electron-redux/tree/master.svg?style=svg)](https://circleci.com/gh/hardchor/electron-redux/tree/master)
[![Greenkeeper badge](https://badges.greenkeeper.io/hardchor/electron-redux.svg)](https://greenkeeper.io/)
[![build status](https://github.com/partheseas/electron-redux/workflows/main/badge.svg)](https://github.com/partheseas/electron-redux/actions)
[![package version](https://mckay.la/vbadge/@mckayla%2Felectron-redux/afbdf7)](https://npmjs.com/package/@mckayla/electron-redux)
[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://prettier.io)

- [electron-redux](#electron-redux)
- [Motivation](#motivation)
- [The solution](#the-solution)
- [Install](#install)
- [Actions](#actions)
- [Local actions (renderer process)](#local-actions-renderer-process)
- [Aliased actions (main process)](#aliased-actions-main-process)
- [Blacklisted actions](#blacklisted-actions)
- [Contributions](#contributions)
- [Contributors](#contributors)
![electron-redux data flow](https://cloud.githubusercontent.com/assets/307162/20675737/385ce59e-b585-11e6-947e-3867e77c783d.png)

## Motivation

Using redux with electron poses a couple of problems. Processes ([main](https://github.com/electron/electron/blob/master/docs/tutorial/quick-start.md#main-process) and [renderer](https://github.com/electron/electron/blob/master/docs/tutorial/quick-start.md#renderer-process)) are completely isolated, and the only mode of communication is [IPC](https://github.com/electron/electron/blob/master/docs/api/ipc-main.md).

- Where do you keep the state?
- How do you keep the state in sync across processes?

### The solution

`electron-redux` offers an easy to use solution. The redux store on the main process becomes the single source of truth, and stores in the renderer processes become mere proxies. See [under the hood](#under-the-hood).

![electron-redux basic](https://cloud.githubusercontent.com/assets/307162/20675737/385ce59e-b585-11e6-947e-3867e77c783d.png)

## Install

```
npm install --save electron-redux
```

`electron-redux` comes as redux middleware that is really easy to apply:
Keeps your state in sync across all of your Electron processes by playing your actions
in all of them.

```javascript
// in the main store
import { forwardToRenderer, triggerAlias, replayActionMain } from 'electron-redux';

const todoApp = combineReducers(reducers);

const store = createStore(
todoApp,
initialState, // optional
applyMiddleware(
triggerAlias, // optional, see below
...otherMiddleware,
forwardToRenderer, // IMPORTANT! This goes last
),
);

replayActionMain(store);
// in the main process
import { syncMain } from "@mckayla/electron-redux";
const store = createStore(reducer, syncMain);
```

```javascript
// in the renderer store
import { forwardToMain, replayActionRenderer, getInitialStateRenderer } from 'electron-redux';

const todoApp = combineReducers(reducers);
const initialState = getInitialStateRenderer();

const store = createStore(
todoApp,
initialState,
applyMiddleware(
forwardToMain, // IMPORTANT! This goes first
...otherMiddleware,
),
);

replayActionRenderer(store);
// in the renderer processes
import { syncRenderer } from "@mckayla/electron-redux";
const store = createStore(reducer, syncRenderer);
```

Check out [timesheets](https://github.com/hardchor/timesheets/blob/4991fd472dbb12b0c6e6806c6a01ea3385ab5979/app/shared/store/configureStore.js) for a more advanced example.

And that's it! You are now ready to fire actions without having to worry about synchronising your state between processes.
That's it! Just add these enhancers to where you initialize your store. As long
as your reducers are pure/deterministic (which they already should be) your state
should be reproduced accurately across all of the processes.

## Actions

Actions fired **MUST** be [FSA](https://github.com/acdlite/flux-standard-action#example)-compliant, i.e. have a `type` and `payload` property. Any actions not passing this test will be ignored and simply passed through to the next middleware.
Actions **MUST** be [FSA](https://github.com/acdlite/flux-standard-action#example)-compliant,
i.e. have a `type` and `payload` property. Any actions not passing this test will
be ignored and simply passed through to the next middleware.

> NB: `redux-thunk` is not FSA-compliant out of the box, but can still produce compatible actions once the async action fires.

Furthermore, actions (and that includes `payload`s) **MUST** be (de-)serialisable, i.e. either POJOs (simple `object`s - that excludes native JavaScript or DOM objects like `FileList`, `Map`, etc.), `array`s, or primitives. For workarounds, check out [aliased actions](#aliased-actions-main-process)
Actions **MUST** be serializable

### Local actions (renderer process)
- Objects with enumerable properties
- Arrays
- Numbers
- Booleans
- Strings
- Maps
- Sets

By default, all actions are being broadcast from the main store to the renderer processes. However, some state should only live in the renderer (e.g. `isPanelOpen`). `electron-redux` introduces the concept of action scopes.
### Local actions

To stop an action from propagating from renderer to main store, simply set the scope to `local`:
By default, all actions are played in all processes. If an action should only be
played in the current thread, then you can set the scope meta property to local.

```javascript
function myLocalActionCreator() {
return {
type: 'MY_ACTION',
payload: 123,
meta: {
scope: 'local',
},
};
}
```

### Aliased actions (main process)

Most actions will originate from the renderer side, but not all should be executed there as well. A great example is fetching of data from an external source, e.g. using [promise middleware](https://github.com/acdlite/redux-promise), which should only ever be executed once (i.e. in the main process). This can be achieved using the `triggerAlias` middleware mentioned [above](#install).

Using the `createAliasedAction` helper, you can quite easily create actions that are are only being executed in the main process, and the result of which is being broadcast to the renderer processes.

```javascript
import { createAliasedAction } from 'electron-redux';

export const importGithubProjects = createAliasedAction(
'IMPORT_GITHUB_PROJECTS', // unique identifier
(accessToken, repoFullName) => ({
type: 'IMPORT_GITHUB_PROJECTS',
payload: importProjects(accessToken, repoFullName),
}),
);
const myLocalActionCreator = () => ({
type: "MY_ACTION",
payload: 123,
meta: {
scope: "local", // only play the action locally
},
});
```

Check out [timesheets](https://github.com/hardchor/timesheets/blob/4ccaf08dee4e1a02850b5bf36e37c537fef7d710/app/shared/actions/github.js) for more examples.

### Blacklisted actions
We also provide a utility function for this

By default actions of certain type (e.g. starting with '@@') are not propagated to the main thread. You can change this behaviour by using `forwardToMainWithParams` function.

```javascript
// in the renderer store
import {
forwardToMainWithParams,
replayActionRenderer,
getInitialStateRenderer,
} from 'electron-redux';

const todoApp = combineReducers(reducers);
const initialState = getInitialStateRenderer();

const store = createStore(
todoApp,
initialState,
applyMiddleware(
forwardToMainWithParams(), // IMPORTANT! This goes first
...otherMiddleware,
),
);

replayActionRenderer(store);
```

You can specify patterns for actions that should not be propagated to the main thread.

```javascript
forwardToMainWithParams({
blacklist: [/^@@/, /^redux-form/],
});
import { stopForwarding } from "@mckayla/electron-redux";
dispatch(stopForwarding(action));
```

## Contributions

Contributions via [issues](https://github.com/hardchor/electron-redux/issues/new) or [pull requests](https://github.com/hardchor/electron-redux/compare) are hugely welcome!

Feel free to let me know whether you're successfully using `electron-redux` in your project and I'm happy to add them here as well!

## Contributors

Special thanks go out to:

- [Charlie Hess](https://github.com/CharlieHess)
- [Roman Paradeev](https://github.com/sameoldmadness)
- Anyone who has contributed by [asking questions & raising issues](https://github.com/hardchor/electron-redux/issues?q=is%3Aissue+is%3Aclosed) 🚀
- [Burkhard Reffeling](https://github.com/hardchor)
- [Charlie Hess](https://github.com/CharlieHess)
- [Roman Paradeev](https://github.com/sameoldmadness)
Loading