jedireza / hapi-react-views Goto Github PK
View Code? Open in Web Editor NEW:package: A hapi view engine for React components
License: MIT License
:package: A hapi view engine for React components
License: MIT License
I do not know why it returns a span when I map in a array...
vision
pluginI cannot use onClick within a view. Maybe I am doing it wrong.
Code to reproduce
var React = require('react')
class Hello extends React.Component {
handleClick() {
console.log("click")
}
render() {
return (
<button onClick={this.handleClick}>Hello</button>
)
}
}
module.exports = Hello
hapi: 13.3
hapi-react-views: 7.0
react: 15.0.2
I just updated the vision examples -- one of which uses this plugin for examples/jsx. I've got react 16 as a dependency and I'm running into [email protected] requires a peer of [email protected]
If you want, I'd be willing to submit a PR
Just found this bug in the Layout feature.
const layoutPath = Path.join(renderOpts.layoutPath, renderOpts.layout + '.jsx');
That hardcodes .jsx
which... is less than optimal. Thoughts as to a workaround? (not all projects use .jsx
as the extension - in fact none of the ones I've worked on - closed or open - do).
Originally I had that variable as a full filename - so without the string concatenation. Thoughts?
(full disclosure, I'm writing this fork atm, would love to be able to issue a PR later to add it into the main stream)
My use case: I want the entire document tree (HTML, Head, etc) rendered by React on the server (controlled by a Store, etc) but this is problematic on the Client if you want to have the ability to embed third party scripts, analytics, etc. So you need to have the client render the core of your app somewhere in the Body.
If you render into a component other than HTML (when you're controlling the whole document on the server) then checksums will fail (assuming renderToStaticMarkup) because the reactroot
is different when you render on the client - and if you don't use checksums then you're blitzing the node content which defeats some of the performance gains from having an Isomorphic app.
IDEALLY I'd have the ability to have a wrapper for whatever view I pass. This wrapper would always be use rendertoString
and the wrapped component would use whatever was set in options (in my case renderToStaticMarkup). This is probably best handled in the options as a config.
Handling it in the options allows overriding it in the reply interface as well - which is very helpful.
an example:
reply.view("myAppComponent", componentPropsObj, {wrapper: myHTMLComponent, wrapperProps: wrapperPropsObj})
Thoughts on if this would be a desired optional feature? It certainly is extremely useful for fully controlled apps.
Wondering if it's already possible, or if not if it could be made possible to use .js
for view extensions.
I prefer to transpile my code and babel renames the .jsx
to .js
in the output directory. I run my server from the dist transpiled directory.
I'm working around it currently with a separate gulp task that uses gulp-extname to force a .jsx extension in the output directory, but it'd be much cleaner if I could just use .js to begin with and have server.render
find the .js
view.
Thanks for the great project by the way!
Currently, removeCache
is only supported by .jsx
extensions as stated in the README. However, I think I found an easy way to remove the current view and layout no matter what the extension. Let me know if I'm misunderstanding why you're removing all .jsx
modules from cache.
How to add a script block to the layout ?
I use Babel CLI for production to compile my ES6 code to ES5. The files with the extension .jsx
be compiled to .js
. The server will only recognize the .jsx
ending. How do you solve the problem?
server.views({
engines: {
jsx: HapiReactViews,
},
compileOptions: {
doctype: '',
},
relativeTo: __dirname,
path: 'views',
});
Is is possible to use view helpers in the react views? For instance, I'm trying to use hapi-named-routes [1]
in the views to generate urls correctly. If not, what's the best practice for utilising useful methods (mixins?) in react views that require server context.
I was able to get the example view.jsx file to show by putting this in my handler.
reply.view(view, { title : 'test' })
but here is whats confusing. view.jsx doesn't have the usual React.render ( "< Component />", 'div');
Is there a working example with react router?
Router.run(routes, function (Handler) {
React.render(<Handler/>, document.body);
});
Wondering if there's a timeline for supporting the latest version of React. Thanks.
I recently opened an issue on Lab that doesn't seem to really have anything to do with it. Since I encountered this while working with hapi-react-views
, I thought I'd throw this here too, just in case.
Looks like Lab doesn't also report coverage errors if I comment out any fixtures in hapi-react-views
itself. It begins to care about coverage only if I comment out the require('babel-register')
(of course in addition to other test failures).
In my own test project I've tried requiring babel-register
inside of a dummy plugin, and then registering it at the end after all the other plugins:
// babel-registrar.js
require('babel-register')({
presets: ['react', 'es2015']
});
exports.register = function (server, options, next) {
next();
};
exports.register.attributes = {
name: 'babel-registrar'
};
// manifest.js
...
plugins: {
'vision': {},
'visionary': {...},
...,
'./babel-registrar': {}
}
...
This somehow defers whatever's causing this issue and makes Lab start reporting coverage again. Would you know what may be the problem and if there's a better way to fix this?
@bkonkle seems to have a good enhancement for path handling in the following commit.
https://github.com/bkonkle/hapi-react-views/commit/6f7e68ac9df837c79f12ce0f8ec7b1c46f59ac03
Using relativeTo
seems like the right way to do it.
I am in the process of updating a project from react 13 to 14 and hapi 11 along with updating to all the latest node modules in the project (based on dependencies). I've been able to sort out all the issues but am stuck on this one as it says it is an internal error. It seems to point to issue with rendering views by hapi-react-views but there is not enough info in the debug for me to figure it out. It appears to be an issue with an unexpected token <: but the project uses babel loader on all the jsx files. I have tried using the useNodeJsx:false in the manifest and that had no effect.
Is there some sort of compatibility issue with hapi-react-views and vision?
Here is the debug output. Any insight is appreciated.
Debug: internal, implementation, error
SyntaxError: Unexpected token <: Unexpected token <
at exports.runInThisContext (vm.js:53:16)
at Module._compile (module.js:414:25)
at Object.Module._extensions..js (module.js:442:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:311:12)
at Module.require (module.js:366:17)
at require (module.js:385:17)
at runtime (C:\Data\captchatheprize.com\dev\gamewww\node_modules\hapi-react-views\index.js:24:25)
at Object.renderer (C:\Data\captchatheprize.com\dev\gamewww\node_modules\vision\lib\manager.js:143:36)
at internals.Manager._loadPartials.internals.Manager._loadHelpers.internals.Manager.render.internals.Manager._prepare.internals.Manager._prepareEngine.internals.Manager._prepareTemplates.callback._path.internals.Manager._path.internals.Manager._render.compiled.template [as _render] (C:\Data\captchatheprize.com\dev\gamewww\node_modules\vision\lib\manager.js:470:14)
at Object.internals.Manager._loadPartials.internals.Manager._loadHelpers.internals.Manager.render.internals.Manager._prepare.internals.Manager._prepareEngine.internals.Manager._prepareTemplates.callback._path.internals.Manager._path.internals.Manager._render.internals.Manager._compile.internals.marshal.callback [as marshal] (C:\Data\captchatheprize.com\dev\gamewww\node_modules\vision\lib\manager.js:564:13)
at internals.Response._prepare.internals.Response._processPrepare.internals.Response._marshal.next [as _marshal] (C:\Data\captchatheprize.com\dev\gamewww\node_modules\hapi\lib\response.js:464:22)
at C:\Data\captchatheprize.com\dev\gamewww\node_modules\hapi\lib\transmit.js:124:18
at C:\Data\captchatheprize.com\dev\gamewww\node_modules\hapi\lib\transmit.js:508:20
at done (C:\Data\captchatheprize.com\dev\gamewww\node_modules\hapi\node_modules\items\lib\index.js:63:25)
at autoValue (C:\Data\captchatheprize.com\dev\gamewww\node_modules\hapi\lib\transmit.js:479:20)
at Object.exports.parallel (C:\Data\captchatheprize.com\dev\gamewww\node_modules\hapi\node_modules\items\lib\index.js:70:13)
at Object.exports.send.internals.marshal.internals.fail.internals.transmit.internals.state.Items.parallel [as state] (C:\Data\captchatheprize.com\dev\gamewww\node_modules\hapi\lib\transmit.js:501:11)
at Object.exports.send.internals.marshal.internals.state [as marshal] (C:\Data\captchatheprize.com\dev\gamewww\node_modules\hapi\lib\transmit.js:98:15)
at Object.exports.send.callback [as send] (C:\Data\captchatheprize.com\dev\gamewww\node_modules\hapi\lib\transmit.js:30:15)
at transmit (C:\Data\captchatheprize.com\dev\gamewww\node_modules\hapi\lib\request.js:439:18)
at C:\Data\captchatheprize.com\dev\gamewww\node_modules\hapi\lib\protect.js:52:16
If I try to convert your layout
example to use ES6 classes, I'm getting an error. However, I am able to convert the home.jsx.
For example, changing only the home.jsx
works with:
const React = require('react');
const Layout = require('./layout.jsx');
export default class Component extends React.Component {
render() {
return (
<Layout title="Home Page">
<h1>Welcome to the plot device.</h1>
</Layout>
);
}
}
However, when I convert the layout.jsx
file as well like this:
const React = require('react');
export default class Component extends React.Component {
render() {
return (
<html>
<head>
<title>{this.props.title}</title>
</head>
<body>
{this.props.children}
<hr />
<p>
<a href="/">Home</a> | <a href="/about">About Us</a>
</p>
</body>
</html>
);
}
}
I get this error:
Warning: React.createElement: type should not be null, undefined, boolean, or number. It should be a string (for DOM elements) or a ReactClass (for composite components). Check the render method of `Component`.
Debug: internal, implementation, error
Error: Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object. Check the render method of `Component`.: Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object. Check the render method of `Component`.
at invariant (/Users/user/dev/hapi-react-views/node_modules/fbjs/lib/invariant.js:39:15)
at [object Object].instantiateReactComponent [as _instantiateReactComponent] (/Users/user/dev/hapi-react-views/node_modules/react/lib/instantiateReactComponent.js:64:134)
at [object Object].ReactCompositeComponentMixin.mountComponent (/Users/user/dev/hapi-react-views/node_modules/react/lib/ReactCompositeComponent.js:223:36)
at [object Object].wrapper [as mountComponent] (/Users/user/dev/hapi-react-views/node_modules/react/lib/ReactPerf.js:66:21)
at /Users/user/dev/hapi-react-views/node_modules/react/lib/ReactServerRendering.js:70:32
at ReactServerRenderingTransaction.Mixin.perform (/Users/user/dev/hapi-react-views/node_modules/react/lib/Transaction.js:136:20)
at Object.renderToStaticMarkup (/Users/user/dev/hapi-react-views/node_modules/react/lib/ReactServerRendering.js:68:24)
at runtime (/Users/user/dev/hapi-react-views/index.js:31:58)
at Object.renderer (/Users/user/dev/hapi-react-views/node_modules/vision/lib/manager.js:141:36)
at [object Object].internals.Manager._loadPartials.internals.Manager._loadHelpers.internals.Manager.render.internals.Manager._prepare.internals.Manager._prepareEngine.internals.Manager._prepareTemplates.callback._path.internals.Manager._path.internals.Manager._render.compiled.template [as _render] (/Users/user/dev/hapi-react-views/node_modules/vision/lib/manager.js:468:14)
Am I implementing this correctly?
via @bkonkle
The "Path.join()" calls in
test/index.js
andREADME.md
aren't actually necessary anymore, because you're not joining anything.
Hello.
I'm trying to use your plugin in my app but I've came across with a question: How can I use Push state ( for React routing ) in Hapi react views?
I've tried:
server.views({
engines: {
jsx: HapiReactViews
},
relativeTo: __dirname,
path: 'src',
compileOptions: {
renderToString: true
}
});
server.route({
method: 'GET',
path: '/{param*}',
handler: {
view: 'Default'
}
});
and this works but all my static files ( images and styles mainly ) are transferred with the wrong Mime type.
If I use a path like this:
path: '/'
My routing works only if I initiate in the '/' URL. The navigation works but when I try to refresh inside a path ( e.g /users/1 ) it shows a 404 error.
Does the best option ( and only ) would be to explicit make "several routes" for my react routes routes in my server.js?
Something like:
server.route({
method: 'GET',
path: '/',
handler: {
view: 'Default'
}
});
server.route({
method: 'GET',
path: '/users/{id}',
handler: {
view: 'Default'
}
});
Thanks!
would you consider supporting additional rendering approaches?
i'd like to use emotion and support SSR of styles, which would require processing with emotion after rendering the component.
i'm sure you dont want to couple this plugin to emotion, so the best option might be to allow providing a function for renderMethod
in addition to the current string options. it could expect to receive ViewElement
and context
as input and return the viewOutput
string.
for example:
import { renderToString } from 'react-dom/server'
import { renderStylesToString } from 'emotion-server'
const context = { name: 'Steve' };
const renderOpts = {
runtimeOptions: {
doctype: '<!DOCTYPE html>',
renderMethod: (ViewElement, context) => {
return renderStylesToString(renderToString(ViewElement(context)));
}
}
};
const output = await server.render('template', context, renderOpts);
i'd be open to sending a PR if this seems like a reasonable option to you.
Trying the plugin out right now with just the example code and getting that.
Not breaking anything at the moment but I imagine it will down the road.
Hi..
Just a question: Is it safe to use babel-register ( mandatory for the JSX View ) in production? I'm currently using your package in a small app but after doing some tweaks I've stumbled into this.
Any thoughts?
Thanks
Sorry to bother again, but is there any support for hot module reloading of serve side components? Not sure if this would be done through hapi-react-views but my client side code is reloading but not the server. Also adding nodemon seems to create a lot of extra emissions versus running the server with just node. Haven't found any info on this anywhere but if it's possible having an example here would be very helpful.
I'm pretty new to React and having a hard time understanding how multiple views (pages) are rendered when using this module to set up an isomorphic application.
I see that client.js calls render on app.jsx, but how does this work when you have more than just app.jsx? I created two separate views, but it looks like the second page is trying to render with app.jsx. How do I set this up to accept multiple views? If this isn't what I should be doing, can you tell me how I should be going about this?
Just wanted to let you know.
git clone [email protected]:jedireza/hapi-react-views.git
In the Example section of the README gives a permissions error. I had to clone it by using the clone/download green button instead.
Tiny issue, but thought you would like to know.
This is obviously not an issue, but a possible enhancement: Currently we compile the htmlOutput and then send it over the wire, we could instead leverage streaming the contents down by using https://github.com/FormidableLabs/rapscallion, which imho nailed it.
Hello,
I tried to use hapi 17 with hapi-react-views and mongo-models (hapi-mongo-models) and I found the issue when I joined all together.
In general, babel (required by React) creates an error when I try to use a model.
Recommendation if using react-views and mongo-models add to app .babelrc with:
{ "ignore": [ "server/api/*.js", "server/models/*.js" ] }
(replace my path with your).
ps. maybe this should go to hapi-mongo-models :-)
See: https://github.com/jedireza/hapi-react-views/blob/master/index.js#L37-L42
We may be able to simply remove the current require
d module by key (constant time vs looping over everything). An added benefit would be that we wouldn't need to worry about the file extension used and could remove the regex check also.
Please update this to only use hapi dependencies from the new @hapi/
scoped modules. This will help me keep it used in vision tests. Let me know if you need help.
I was trying to add forms and events (onSubmit, onChange, onClick) to a template. It seems those do not get attached to the rendered html output?
`
import React from 'react'
class Component extends React.Component {
constructor() {
super()
this.state = {clicked: false}
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({clicked: !this.state.clicked})
}
render() {
return (
export default Component
`
Any hints?
Is it possible to create an example. If possible a somewhat complex example with multiple components and working client side injecting of React (with renderToString)?
Curious on your thoughts on how easy it might be to add some transpiling middlware to parse .tsx templates in Typescript?
I using layoutPath, to set layout default in view engine.
How to pass props to layout.jsx inside view.jsx. Pass from handler.js is ok. but i want set props inside view to layout.
It is magic layout same: https://github.com/jedireza/hapi-react-views/tree/master/examples/layout
Not using tag element layout.
Thanks you.
I was trying to add forms and events (onSubmit, onChange, onClick) to a template. It seems those do not get attached to the rendered html output?
import React from 'react'
class Component extends React.Component {
constructor() {
super()
this.state = {clicked: false}
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({clicked: !this.state.clicked})
}
render() {
return (
<div>
<form>
<div onClick={this.handleClick}> Click </div>
</form>
</div>
)
}
}
export default Component
Any hints?
the doc says when using another jsx-transformer instead of node-jsx
, one should set useNodeJsx
to false
.
i want to use babel as the transformer, my configuration looks like this:
'visionary': {
engines: {
jsx: 'hapi-react-views'
},
compileOptions: { useNodeJsx: false },
relativeTo: __dirname,
path: './server/views'
}
i simply added require(babel/register)
at the top of home.jsx
, then this error occurred.
Debug: internal, implementation, error
/Users/gnimuc/Documents/test/server/views/home.jsx:25
<div className="commentBox">
^
SyntaxError: Unexpected token <
i guess this is not the correct way to change the jsx-transformer.
i'm very new to nodejs, sorry for disturbing.
[1] ==> ๐ Listening at http://localhost:8000
[1] Debug: internal, implementation, error
[1] SyntaxError: Unexpected token <: Unexpected token <
[1] at exports.runInThisContext (vm.js:53:16)
[1] at Module._compile (module.js:414:25)
[1] at Object.Module._extensions..js (module.js:442:10)
[1] at Module.load (module.js:356:32)
[1] at Function.Module._load (module.js:311:12)
[1] at Module.require (module.js:366:17)
[1] at require (module.js:385:17)
[1] at runtime (/Project/node_modules/hapi-react-views/index.js:22:25)
[1] at Object.renderer (/Project/node_modules/vision/lib/manager.js:142:36)
[1] at internals.Manager._render (/Project/node_modules/vision/lib/manager.js:477:14)
[1] at Object.internals.marshal (/Project/node_modules/vision/lib/manager.js:571:13)
[1] at internals.Response._prepare.internals.Response._processPrepare.internals.Response._marshal.next [as _marshal] (/Project/node_modules/hapi/lib/response.js:464:22)
[1] at /Project/node_modules/hapi/lib/transmit.js:124:18
[1] at /Project/node_modules/hapi/lib/transmit.js:499:20
[1] at Object.exports.parallel (/Project/node_modules/hapi/node_modules/items/lib/index.js:47:9)
[1] at Object.exports.send.internals.marshal.internals.fail.internals.transmit.internals.state.Items.parallel [as state] (/Project/node_modules/hapi/lib/transmit.js:492:11)
Thanks so much for this lib, really enjoying it! Just experimenting with your layout example and I need to ask, how can I set this.props.title
?
I tried setting defaultProps
in Auth.tsx
(just a component):
import * as React from 'react'
interface ILayoutProps {
title: string
}
export default class extends React.Component<ILayoutProps, undefined> {
public static defaultProps: ILayoutProps = {
title: 'Authenticate'
}
public render () {
return (
<a href="/auth/google/callback">Login with Google</a>
)
}
}
But this.props.title
is still undefined
in Layout
๐ฒ
Any thoughts? Thanks!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.