Last active
March 29, 2019 01:15
-
-
Save ktec/58225384aa0222b496713aebb3fe0af3 to your computer and use it in GitHub Desktop.
HOW TO USE PHOENIX WITH WEBPACK + REACT + REDUX - This is a collection of small changes related to: https://www.dailydrip.com/blog/how-to-use-phoenix-with-webpack-react-redux.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export const SEND_MESSAGE = 'SEND_MESSAGE'; | |
function sendMessage(message) { | |
return { | |
type: SEND_MESSAGE, | |
payload: { | |
message | |
} | |
}; | |
} | |
export default { sendMessage }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { Component } from "react"; | |
import { connect } from "react-redux"; | |
import MessageList from "../components/MessageList"; | |
import MessageInput from "../components/MessageInput"; | |
import Actions from "../actions"; | |
function App(props) { | |
const { messages, sendMessage } = props; | |
return ( | |
<div> | |
<MessageList messages={messages} /> | |
<MessageInput onClick={sendMessage} /> | |
</div> | |
); | |
} | |
export const AppContainer = connect( | |
function mapStateToProps(state) { | |
return { | |
messages: state.mainReducer.get("messages") | |
}; | |
}, | |
function mapDispatchToProps(dispatch) { | |
return { | |
sendMessage: message => { | |
dispatch(Actions.sendMessage(message)); | |
} | |
}; | |
} | |
)(App); | |
export default AppContainer; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from "react"; | |
import { render } from "react-dom"; | |
import { Provider } from "react-redux"; | |
import App from "./containers/App"; | |
import MyStore from "./store"; | |
render( | |
<Provider store={MyStore}> | |
<App /> | |
</Provider>, | |
document.getElementById("root") | |
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule XxxWeb.LayoutView do | |
use XxxWeb, :view | |
def js_script_tag do | |
# This assumes config is setup | |
if Application.get(:xxx, :webpack_dev_server) == :enabled do | |
# In development mode we'll load it from our webpack dev server | |
"<script src=\"http://localhost:8080/js/app.js\"></script>" | |
else | |
# In production we'll just reference the file | |
"<script src=\"/js/index.js\"></script>" | |
end | |
end | |
# Ditto for the css | |
def css_link_tag do | |
if Application.get(:xxx, :webpack_dev_server) == :enabled do | |
"<link rel=\"stylesheet\" type=\"text/css\" href=\"http://localhost:8080/css/app.css\" />" | |
else | |
"<link rel=\"stylesheet\" type=\"text/css\" href=\"/css/app.css\" />" | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from "react"; | |
function MessageInput(props) { | |
const { onClick } = props; | |
let inputRef; | |
return ( | |
<div> | |
<input type="text" ref={node => inputRef = node} /> | |
<button onClick={() => onClick(inputRef.value)}> | |
SEND | |
</button> | |
</div> | |
) | |
} | |
export default MessageInput; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from "react"; | |
function MessageList(props) { | |
const { messages } = props; | |
const renderMessage = (message, key) => { | |
return <div key={key}>{message.text}</div>; | |
} | |
const renderMessages = messages.map(renderMessage); | |
return <div className="message-list">{renderMessages}</div>; | |
} | |
export default MessageList; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "xxx", | |
"version": "0.1.0", | |
"description": "xxx", | |
"main": "js/index.js", | |
"private": true, | |
"dependencies": { | |
"copy-webpack-plugin": "^4.1.1", | |
"immutable": "^3.8.2", | |
"react": "^16.0.0", | |
"react-dom": "^16.0.0", | |
"react-redux": "^5.0.6", | |
"redux": "^3.7.2", | |
"redux-immutable": "^4.0.0", | |
"redux-thunk": "^2.2.0", | |
"webpack": "^3.8.0", | |
"webpack-dev-server": "^2.9.2" | |
}, | |
"devDependencies": { | |
"babel-core": "^6.26.0", | |
"babel-loader": "^7.1.2", | |
"babel-plugin-transform-class-properties": "^6.24.1", | |
"babel-plugin-transform-object-rest-spread": "^6.26.0", | |
"babel-preset-env": "^1.6.0", | |
"babel-preset-es2015": "^6.24.1", | |
"babel-preset-react": "^6.24.1", | |
"css-loader": "^0.28.7", | |
"extract-text-webpack-plugin": "^3.0.1", | |
"import-glob-loader": "^1.1.0", | |
"node-sass": "^4.5.3", | |
"sass-loader": "^6.0.6", | |
"style-loader": "^0.19.0" | |
}, | |
"scripts": { | |
"webpack": "webpack-dev-server --watch --color" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// @flow | |
import { List } from "immutable"; | |
import { combineReducers } from "redux"; | |
import { Model, MessageType } from "./types"; | |
import { SEND_MESSAGE } from './actions'; | |
const init = new Model(); | |
type ActionType = SEND_MESSAGE; | |
function mainReducer( | |
model: Model = init, | |
action: { type: ActionType, payload: Object } | |
) { | |
switch (action.type) { | |
case SEND_MESSAGE: | |
return sendMessage(model, action.payload); | |
default: | |
return model; | |
} | |
} | |
function nullReducer( | |
model: Model = init, | |
action | |
) { | |
switch (action.type) { | |
default: | |
return model; | |
} | |
} | |
// private function!! | |
function sendMessage(model, payload) { | |
if (payload) { | |
const message = new MessageType({ text: payload.message }) | |
const new_model = model.updateIn( | |
["messages"], | |
messages => messages.push(message) | |
); | |
return new_model; | |
} else { | |
return model; | |
} | |
} | |
const app = combineReducers({ | |
mainReducer, | |
nullReducer | |
}); | |
export default app; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// @flow | |
import reducers from "./reducers"; | |
import { createStore, applyMiddleware, compose } from "redux"; | |
import thunk from "redux-thunk"; | |
function composeWithApplyMiddlewares() { | |
if (window.__REDUX_DEVTOOLS_EXTENSION__) { | |
return compose( | |
applyMiddleware(thunk), | |
window.__REDUX_DEVTOOLS_EXTENSION__() | |
); | |
} | |
return compose(applyMiddleware(thunk)); | |
} | |
const createMyStore = () => { | |
return createStore( | |
reducers, | |
{}, | |
composeWithApplyMiddlewares() | |
); | |
}; | |
export default createMyStore(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var webpack = require("webpack"); | |
var path = require("path"); | |
// We'll be using the ExtractTextPlugin to extract any required CSS into a | |
// single CSS file | |
const ExtractTextPlugin = require("extract-text-webpack-plugin"); | |
// We'll use CopyWebpackPlugin to copy over static assets like images and | |
// fonts | |
const CopyWebpackPlugin = require("copy-webpack-plugin"); | |
var env = process.env.MIX_ENV || "dev"; | |
var isProduction = env === "prod"; | |
// We'll set up some paths for our generated files and our development server | |
const staticDir = path.join(__dirname, "."); | |
const destDir = path.join(__dirname, "../priv/static"); | |
const publicPath = "/"; | |
module.exports = { | |
entry: [ | |
staticDir + "/js/index.js", | |
staticDir + "/css/app.scss" | |
], | |
output: { | |
path: destDir, | |
filename: "js/app.js", | |
publicPath | |
}, | |
module: { | |
loaders: [ | |
{ | |
test: /\.jsx?$/, | |
loader: 'babel-loader', | |
exclude: /node_modules/, | |
query: { | |
presets: [ | |
["es2015"], | |
["react"], | |
[ | |
"env", | |
{ | |
"targets": { | |
"browsers": ["last 2 versions", "safari >= 7"] | |
}, | |
"include": ["transform-es2015-arrow-functions", "es6.map"], | |
"exclude": [] | |
} | |
] | |
], | |
plugins: [ | |
["transform-object-rest-spread", { "useBuiltIns": true }], | |
["transform-class-properties", { "spec": true }] | |
] | |
} | |
}, | |
// Any CSS or SCSS files will run through the css loader, the sass | |
// loader, and the import-glob-loader. The last one will allow us to use | |
// glob patterns to import SCSS files - for instance, a whole directory of | |
// them. That isn't available by default in node-sass | |
{ | |
test: /\.s?css$/, | |
exclude: [path.resolve(__dirname, "node_modules")], | |
loader: ExtractTextPlugin.extract({ | |
fallback: 'style-loader', | |
use: ['css-loader', 'sass-loader', 'import-glob-loader'] | |
}) | |
} | |
] | |
}, | |
// And we'll configure our ExtractTextPlugin and CopyWebpackPlugin | |
plugins: [ | |
new ExtractTextPlugin("css/app.css"), | |
// We copy our images and fonts to the output folder | |
new CopyWebpackPlugin([{ from: "./static/images", to: "images" }]) | |
] | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment