Git Product home page Git Product logo

react-phoenix's Introduction

ReactPhoenix

Build Status Hex.pm

Functions to make rendering React.js components easy in Phoenix.

Combined with the javascript also included in this package, rendering React components in your Phoenix views is now much easier. Using the Phoenix default of Webpack, this package can make getting React into your application much faster than switching over to a different system.

Note regarding Phoenix versions <= 1.3

Phoenix versions 1.3 and earlier use Brunch by default instead of Webpack for asset compilation. The setup for apps using Brunch is different than apps using Webpack. If you'd like to read the old guide for 1.3/Brunch, you can read the Phoenix 1.3 README.

Installation in 4 (or 5) EASY STEPS!

This package is meant to be quick and painless to install into your Phoenix application. It is a thin wrapper to call the React render function from your Phoenix template and assumes you already have React in your project.

1. Declare the dependency

The package can be installed by adding react_phoenix to your list of dependencies in mix.exs:

def deps do
  [
    {:react_phoenix, "~> 1.3"}
  ]
end

After adding to your mix file, run:

mix deps.get

2. Add the javascript dependency to package.json

In order to correctly render a React component in your view templates, a provided javascript file must be included in your assets/package.json file in the dependencies section. It might look like this:

{
  ...
  "dependencies": {
    "phoenix": "file:../deps/phoenix",
    "phoenix_html": "file:../deps/phoenix_html",
    "react": "^16.2.0",
    "react-dom": "^16.2.0",
    "react-phoenix": "file:../deps/react_phoenix" <-- ADD THIS!
  },
  ...
}

Then run (from your assets directory)

npm install

or

yarn

yarn users

If you face the following error using yarn:

Error: "You may need an appropriate loader to handle this file type"

You may need to add the below to your assets/webpack.config.js file.

{ test: /\.jsx$/, use: { loader: 'babel-loader' } }

npm users

npm unfortunately needs an extra bit of configuration to make it happy. Add the following block to your assets/webpack.config.js file. If you use yarn to manage your dependencies, this extra bit of configuration should not be necessary.

module.exports = (env, options) => ({
  ...
  // ADD THIS BLOCK ˅˅˅
  resolve: {
    alias: {
      react: path.resolve(__dirname, './node_modules/react'),
      'react-dom': path.resolve(__dirname, './node_modules/react-dom')
    }
  }
  // ADD THIS BLOCK ^^^
  ...
});

3. Make sure React and Babel presets are installed

Since we want React and would like to write JSX in our app, we need to make sure we get the packages brunch needs in order to compile our files.

# using npm
npm install react react-dom --save
npm install @babel/preset-env @babel/preset-react --save-dev

or

# using yarn
yarn add react react-dom
yarn add --dev @babel/preset-env @babel/preset-react

We also need to activate those presets from the assets/.babelrc file:

// Configure your plugins
{
  "presets": [
    "@babel/preset-env",
    "@babel/preset-react" // <-- ADD THIS!
  ]
}

4. Import and initialize the javascript helper

In your main application javascript file (usually assets/js/app.js), add the following line:

import "react-phoenix"

5. (optional) Import the module into your views for less typing

If you'd like to just call react_component(...) in your views instead of the full ReactPhoenix.ClientSide.react_component(...), you can import ReactPhoenix.ClientSide into your lib/APPNAME_web.ex views section. It might look like this:

def view do
  quote do
    use Phoenix.View,
      root: "web/templates",
      namespace: MyPhoenixApp

    import Phoenix.Controller, only: [get_flash: 1, get_flash: 2, view_module: 1]

    use Phoenix.HTML

    import MyPhoenixApp.ErrorHelpers
    import MyPhoenixApp.Gettext
    alias MyPhoenixApp.Router.Helpers, as: Routes

    import ReactPhoenix.ClientSide # <-- ADD THIS!
  end
end

Usage

Once installed, you can use react_component in your views by:

  1. Making sure that the component you'd like rendered is in the global namespace. You can do that in app.js like this (for example):

    import MyComponent from "./components/my_component"
    window.Components = {
      MyComponent
    }
  2. In your view template, you can then render it like this:

    # with no props
    <%= ReactPhoenix.ClientSide.react_component("Components.MyComponent") %>
    
    # with props
    <%= ReactPhoenix.ClientSide.react_component("Components.MyComponent", %{language: "elixir", awesome: true}) %>
    
    # with props and a target html element id option
    <span id="my-react-span"><%= @react_html %></span>
    <%= ReactPhoenix.ClientSide.react_component("Components.Characters", %{people: people}, target_id: "my-react-span") %>

    This will render a special div element in your html output that will then be recognized by the javascript helper as a div that should be turned into a React component. It will then render the named component in that div (or a different element specified by ID via the target_id option).

What about server-side rendering?

I couldn't quite get this working with Brunch, but I hope to have time to look at it again with Webpack.

Documentation and other stuff

This package is heavily inspired by the react-rails project.

For more detailed documentation, check out the hex docs at https://hexdocs.pm/react_phoenix

react-phoenix's People

Contributors

aboroska avatar andrewmurph avatar barthez avatar behrgood avatar dependabot[bot] avatar geolessel avatar gmora08 avatar haydenrou avatar hdra avatar mfilej avatar scmx avatar tmorton avatar vasspilka avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-phoenix's Issues

Upgrade to `phoenix_html 3.x.x`

Hello. We're using your awesome library in an umbrella app. Because it's using phoenix_html 2.x.x, it prevents us from upgrading to Phoenix 1.6, which depends on phoenix_html 3.x.x.

Are there plans to upgrade to phoenix_html 3.x.x? I may have some time to help with the upgrade.

Poison version with std_json_io_2

I'm getting this message when doing mix deps.get

Failed to use "poison" (version 2.2.0) because
  arc (version 0.6.0) requires ~> 2.0 or ~> 3.0
  ecto (version 2.1.3) requires ~> 2.2 or ~> 3.0
  ex_aws (version 1.0.0) requires >= 1.2.0
  phoenix (version 1.2.1) requires ~> 1.5 or ~> 2.0
  react_phoenix (version 0.4.1) requires ~> 2.2 or ~> 3.0
  std_json_io_2 (version 0.2.0) requires ~> 3.0
  mix.lock specifies 2.2.0

Does std_json_io_2 need poison 3.0 or would an earlier release still work?

is there a way to pass a list of objects?

Thank you for making this awesome repo.

I am wondering if we can pass a list of objects into props? For example: [%{obj_1}, %{obj_2}]? I've tried many ways to pass my Repo.all structures to the component but couldn't.

Any ideas?

Very large app.js

Is there a way to split loads with this library? My app.js is getting very large because I'm loading all components in app.js.

Suppose I load map.js in the correct html.eex file:

webpack.config.js

  entry: {
      app: ['./js/app.js'].concat(glob.sync('./vendor/**/*.js')),
      map: ['./js/Components/idiofaMapShow.js'].concat(glob.sync('./vendor/**/*.js')),
  },

map.js

class MyMap extens React.Component{...}

document.Components
{
  MyMap
}

How to get it working in IE EDGE

Copied everything from the video (https://www.youtube.com/watch?v=icwjAbck8yk)

Everything working fine in chrome/firefox but doesn't want to appear in IE EDGE,

I can see the Div in the dom explorer but nothing after that.

Showing SCRIPT438: Object doesn't support property or method 'forEach' in the console.

Now I've tried using 'import babel-polyfill' in the top of my app.js , but then it doesn't render in chome/firefox and is still showing blank in IE edge.

Apologies if this is a babel/react set up issue, I'm new.

Not swapping in the Component

I've followed the instructions carefully, but my component isn't being swapped into the DOM. I've verified that the component is being compiled in priv/static/js/app.js and the DOM shows the following <div data-react-class="Components.MyComponent" data-react-props="{}"></div>.

Not sure what I'm missing... I'm using :react_phoenix "~>0.5.1", :phoenix, "~> 1.3.0", elixir: "~> 1.4"

Cannot install phoenix 1.2

Hello everybody,
this seems great, but I cannot get it to run:
As in #18 I had to update my debs like so:

{:poison, "~> 2.2", override: true},
{:react_phoenix, "~> 0.4.2"}

I also had to install react-stdio using npm otherwise it would not compile. However, when I try to start a server I get those errors:

Using outdated versions of react-phoenix, trying to update to match package.json versions
01 Jul 22:22:51 - info: Installing npm packages...
(removed not interesting stuff)
Resolving deps of web/static/js/app.js failed. Could not load module 'react-phoenix' from '/Users/Christian/Documents/blog/web/static/js'. Possible solution: run `npm install`. 

package.json:

"dependencies": {
    "draft-js": "^0.10.1",
    "draft-js-plugins-editor": "^2.0.0-rc2",
    "phoenix": "file:deps/phoenix",
    "phoenix_html": "file:deps/phoenix_html",
    "react-phoenix": "file:deps/react_phoenix",
    "react": "^15.6.1",
    "react-dom": "^15.6.1"
  },
  "devDependencies": {
    "babel-brunch": "^6.0.6",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "brunch": "2.7.4",
    "clean-css-brunch": "~2.0.0",
    "css-brunch": "~2.0.0",
    "javascript-brunch": "~2.0.0",
    "react-stdio": "^3.1.0",
    "uglify-js-brunch": "~2.0.1"
  }

Am I missing something or have the requirements for installation changed?

Additional question: I plan to use React in only certain parts of the backend, is it possible to ommit the JS for all other pages?

Thanks a lot in advance.

Don't check react-stdio presence at compile time

Would it be possible to check for react-stdio at runtime instead of compile time? I'm deploying to Heroku, which provides:

  1. A step for installing and compiling Elixir and it's dependencies
  2. A step for installing yarn/npm dependencies.

The way this library currently works requires you to:

  1. Install Elixir & dependencies (to have the react-phoenix.js file available for yarn)
  2. Install yarn dependencies (to have react-stdio available for compilation)
  3. Compile Elixir.

This is an issue, as the buildpacks for Heroku don't provide an easy way to split up the Elixir install/compile steps.

An added benefit is that then we wouldn't require react-stdio to be installed if you aren't using the ServerSide functionality.

npm "no such file or directory", ansi-regex related

I'm using npm 6.1.0, trying to install {:react_phoenix, "~> 0.6"} but get this error:

npm WARN assets No description

npm ERR! path [...]/assets/node_modules/.staging/react-phoenix-9fe48a1f/node_modules/ansi-regex
npm ERR! code ENOENT
npm ERR! errno -2
npm ERR! syscall rename
npm ERR! enoent ENOENT: no such file or directory, rename '[...]/assets/node_modules/.staging/react-phoenix-9fe48a1f/node_modules/ansi-regex' -> '[...]/assets/node_modules/.staging/ansi-regex-174fca70'
npm ERR! enoent This is related to npm not being able to find a file.
npm ERR! enoent 

npm ERR! A complete log of this run can be found in:
npm ERR!     /[...]/.npm/_logs/2018-06-06T10_23_11_585Z-debug.log

updated npm, cleaned caches etc. with no success.
Maybe related to #23

Can't install with Phoenix 1.3 and Elixir 1.4

I'm trying the 0.4.3 release. I keep getting this error:

** (Mix) Could not start application react_phoenix: ReactPhoenix.Application.start(:normal, []) returned an error: shutdown: failed to start child: ReactPhoenix.ReactIo
    ** (EXIT) shutdown: failed to start child: ReactPhoenix.ReactIo.Pool
        ** (EXIT) an exception was raised:
            ** (MatchError) no match of right hand side value: {:error, {:function_clause, [{Porcelain, :spawn_shell, [nil, [in: :receive, out: {:send, #PID<0.541.0>}]], [file: 'lib/porcelain.ex', line: 241]}, {StdJsonIo.Worker, :init, 1, [file: 'lib/std_json_io/worker.ex', line: 12]}, {:gen_server, :init_it, 6, [file: 'gen_server.erl', line: 328]}, {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 247]}]}}
                /Users/mohamad/Code/app/deps/poolboy/src/poolboy.erl:275: :poolboy.new_worker/1
                /Users/mohamad/Code/app/deps/poolboy/src/poolboy.erl:296: :poolboy.prepopulate/3
                /Users/mohamad/Code/app/deps/poolboy/src/poolboy.erl:145: :poolboy.init/3
                (stdlib) gen_server.erl:328: :gen_server.init_it/6
                (stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3

Any ideas?

Error in make a release

Hi, I'm trying to generate a release with distillery but throw this error
Including ERTS 8.3.5.2 from /usr/local/lib/erlang/erts-8.3.5.2�[0m Release failed, during .boot generation: react_phoenix: Missing parameter in .app file: mod�[0m Build step 'Execute shell' marked build as failure

I'm using elixir 1.5.2, erlang 19 and erts-8.3.5.2.

Cannot resolve 'react-dom' and 'react' in react-phoenix/priv/js

Successfully compiles, but when I start server I am seeing
Webpack is watching the files…

Hash: 5d64ea7a3e7aaa72b63b
Version: webpack 4.4.0
Time: 1083ms
Built at: 1/29/2019 11:27:10 PM
Asset Size Chunks Chunk Names
../css/app.css 10.6 KiB ./js/app.js [emitted] ./js/app.js
app.js 85.2 KiB ./js/app.js [emitted] ./js/app.js
../favicon.ico 1.23 KiB [emitted]
../robots.txt 202 bytes [emitted]
../images/phoenix.png 13.6 KiB [emitted]
[../deps/phoenix_html/priv/static/phoenix_html.js] 2.17 KiB {./js/app.js} [built]
[../deps/react_phoenix/priv/js/react_phoenix.js] 1.62 KiB {./js/app.js} [built]
[./css/app.scss] 39 bytes {./js/app.js} [built]
[./js/app.js] 644 bytes {./js/app.js} [built]
[0] multi ./js/app.js 28 bytes {./js/app.js} [built]
+ 8 hidden modules

ERROR in ../deps/react_phoenix/priv/js/react_phoenix.js
Module not found: Error: Can't resolve 'react-dom' in '/${PATH}/deps/react_phoenix/priv/js'

Getting this as well as a similar issue for 'react'. Error is triggered during webpack compilation. I have added the .babelrc and followed documentation accurately. ${PATH} is a shorthand I mutated from original string since the URI was quite long

Router docs

Do you have any suggestions how to handle routing inside react components?

I saw some examples with react-router, but you need to duplicate your routes.

Issue with Phoenix 1.3

I'm trying to use this lib with Phoenix 1.3 and I get the following error on npm install:

enoent ENOENT: no such file or directory, open '/Users/mohamad/Code/example/assets/deps/react_phoenix'

I'm assuming this is to do with assets moving into the root in Phoenix 1.3. What's the best way to solve this?

[question] How to use this lib with Redux?

Still getting to grips with React in general, so excuse the question if it sounds silly. In most examples I've seen, a Redux store is passed to the component when rendering it inside the JS file.

React.renderComponent(<MyComponent state={someStateStoreFromRedux} />, document.body);

Given that react-phoenix lets us render components from our eex templates, how would I go about using it with a Redux store?

Can't install with Phoenix 1.2 (incompatible requirements for poison package)

This package looks awesome, but I've run into a problem installing it in my Phoenix 1.2 app. It seems that phoenix 1.2 requires poison ~> 1.5 or ~> 2.0, but this package requires std_json_io_2 which requires poison 3.0.

▶ mix deps.get
Running dependency resolution...

Failed to use "poison" (version 2.2.0) because
  ecto (version 2.1.4) requires ~> 2.2 or ~> 3.0
  ex_aws (version 1.1.2) requires >= 1.2.0
  phoenix (version 1.2.4) requires ~> 1.5 or ~> 2.0
  react_phoenix (version 0.4.2) requires ~> 2.2 or ~> 3.0
  std_json_io_2 (version 0.2.0) requires ~> 3.0
  wallaby (version 0.16.1) requires >= 1.4.0
  mix.lock specifies 2.2.0

** (Mix) Hex dependency resolution failed, relax the version requirements of your dependencies or unlock them (by using mix deps.update or mix deps.unlock). If you are unable to resolve the conflicts you can try overriding with {:dependency, "~> 1.0", override: true}

I was able to install 0.3.0, which is the last version without the std_json_io_2 dependency. I'll use that for now.

Thanks for the package!

How do I handle transclusion? child elements?

Hi all,

I want to use react-split-pane to do a three-pane vertical layout.

If I was working in pure React, it would look something like:

<threepanes>
<div>Foo</div>
<div>Bar</div>
<div>Baz</div>
</threepanes>

But we're using react-phoenix (which is awesome, thank you!)

But in react-phoenix I can't figure out how to pass child elements.

The best I've managed to figure out is:
image

But this seems like a bit of a kluge; I also have to fake transclusion into the React shadow dom, which turns out to be bizarrely complex.

What's the most idiomatic way of solving this?

Relaxing poison version requirement

Hi, I'm getting this when I try to add it to a phoenix 1.3 project.

Failed to use "poison" (version 3.1.0) because
  arc (version 0.7.0) requires ~> 2.2 or ~> 3.1
  ex_aws (version 1.1.2) requires >= 1.2.0
  phoenix (version 1.3.0-rc.1) requires ~> 2.2 or ~> 3.0
  react_phoenix (version 0.3.0) requires ~> 2.2.0
  mix.lock specifies 3.1.0

What do you think about changing it to "~> 2.2 or ~> 3.0"?
I'm sending a PR.

Consider peer-dependency for react

Hi, some thoughts came to mind from recent error I had that was caused by the "root renderer" using different versions of react than the react components.

Since the setup assumes there is a package.json file for the frontend project, maybe its safe to assume that most people will have their own react project set up separately anyway (through create-react-app or whatever)? In that case, maybe we can consider having react as a peerDependency of the project so that we wouldn't have 2 separate versions of react running.

Also, since the project itself is a thin wrapper around react, maybe can also consider relaxing the version constraint (something like >15, or even *) so that users can decide which version of react to use with their own package.json.

Webpack Error w/ Yarn

Error: "You may need an appropriate loader to handle this file type"

Elixir version: 1.10.3
Erlang version: 23.0
Phoenix version: 1.5.1

Using Yarn, I received the above error which was fixed by adding the below rule to my webpack.config.js file.

{ test: /\.jsx$/, use: { loader: 'babel-loader' } }

I'm happy to submit a PR to the documentation for this, but I just wanted to check I wasn't missing something before I did so.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.