preactjs / preact-render-to-string Goto Github PK
View Code? Open in Web Editor NEW:page_facing_up: Universal rendering for Preact: render JSX and Preact components to HTML.
Home Page: http://npm.im/preact-render-to-string
License: MIT License
:page_facing_up: Universal rendering for Preact: render JSX and Preact components to HTML.
Home Page: http://npm.im/preact-render-to-string
License: MIT License
Hi, I'm experimenting with universal rendering with Preact and I'm running into this strange issue.
I render my HTML on the server using this library. It works well.
But then, when I render to the DOM on the client, it adds the content to the existing nodes instead of replacing it.
To get around this I'm now doing this on the client:
var root = document.getElementById('app-root');
root.innerHTML = '';
render(<App />, root);
Is this the correct way or should I somehow be able to 'mount' render to the existing DOM tree? I am worried that this will give ugly flashes when my app becomes bigger.
I could not find an example of this. Is there one?
Hi
It would be good to have an interface like this:
render(
<Provider store={store}>
<Root/>
</Provider>
).then(({html, context, state}) => { /* all done, serve to client now */ }
So the render promise will only resolve once everything has been rendered and all async actions have been finished. This would make it easier to get the redux state too and you wouldn't have to get the redux state artificially before calling render (plus artificially figuring out the route n stuff - all the things that make the server side different from the client side).
Basically run the complete application server side until its stabilized and ready to render.
I do not know if that is a transpilation problem, but it looks like that when you try to do the following with typescript:
import xyz from "module-with-default-export"
it assumes that a exports.default
exists within module-with-default-export
, which I think is right but it has been a while since I last checked the modules spec. It looks like preact-render-to-string
directly exports a function.
Workaround is to do an:
import * as render from "preact-render-to-string"
But this is schematically wrong if I'm not mistaken.
In the same setup as #43
I noticed that when getComponentName()
is called on inner === true
VNodes, the resolution for the name of the component is often cl
, even though proto.displayName
or proto.name
contains the name of the actual component.
The string cl
is coming from this line: https://github.com/developit/preact-compat/blob/e25d0607d8a00a3e2f9229f33de4dc0f63c8e931/src/index.js#L405
I could fix this in the code with a simple if inside getComponentName
:
if (component.name === 'cl') {
delete component.name;
}
Again, I'm not sure if this is happening due to my setup with preact-compat
or maybe it's related to the preact-compat-enzyme
but it would be nice to know if this is intended operation of if I'm actually doing something wrong.
Can you help to figure this issue out as well?
We have the case that we want to render more elements which can be also void (XML syntax).
It would be good to allow this with an option.
Reference: preactjs/preact#919
<input type="checkbox">
<input type="checkbox" checked="false"></input>
Note that this HTML code generates a checkbox that is checked, because the presence of the checked
attribute.
Not sure if this is a preact
issue or a preact-render-to-string
issue, but I’ll put it here for now.
A component I wrote wasn’t being exported properly (long story) and the result was undefined
instead of a valid component. I thought it was a React alias issue like I saw in a few other issues, but after digging through my bundle I determined that that was not the case.
Seems to me that either h(undefined)
or renderToString( h(undefined) )
should throw an error.
Right now using preact-render-to-string directly you end up with double encoding in the snapshot output
see this twitter thread -- https://twitter.com/stillconor/status/805567906310451200 -- for more details.
cc @developit , I'd be interesting in taking this on if you could provide high level guidance on how this would would be worked on.
I have my own .babelrc
config (which doesn't include babel-preset-es2015
)... why is preact requiring me to install and use the es2015 preset specifically?
ERROR in ./node_modules/preact-render-to-string/dist/index.js
Module build failed: Error: Couldn't find preset "es2015" relative to directory "/Users/me/dev/app/node_modules/preact-render-to-string"
steps to reproduce
use dangerouslySetInnerHTML with renderToJsxString
> const h = require('preact').h
> console.log(require('preact-render-to-string')(<div dangerouslySetInnerHTML={{__html:'<span>foo</span>'}} />))
<div><span>foo</span></div>
undefined
> console.log(require('preact-render-to-string/jsx')(<div dangerouslySetInnerHTML={{__html:'<span>foo</span>'}} />))
<div
dangerouslySetInnerHTML={
Object {
"__html": "<span>foo</span>"
}
}
>
</div>
undefined
expected results
dangerouslySetInnerHTML "executed" in either render method.
actual results
dangerouslySetInnerHTML "executed" only in renderToString, but not renderToJsxString.
notes
i'm using preact-jsx-chai and would rather not use dangerouslySetInnerHTML for hardcoded html in my tests. i've tracked down the issue to this library, but feel free to tell me that it should be addressed in the other one. i didn't see a way to tell that library not to use the jsxString render function.
In some instances, it's not desirable for certain tags to be treated exclusively as self-closing elements, such as with the <link>
tag in RSS feeds. It might be useful to allow an additional option in the renderToString
method to allow users to supply an array of elements they want (or as in this case, don't want) to be treated as self-closing. This may not really be used very much, but in cases where XML is generated, it could be a nice little feature to add.
If you're down, I'm happy to add it. I also see that this has been referenced in a somewhat different way in #52.
render
quietly does nothing when it encounters a Fragment
.
Here's a demo showing the issue.
I'm currently having an issue where preact on the client-side is not taking over the DOM nodes rendered by preact-render-to-string on the server. Am I missing something or does preact not currently take over pre-rendered HTML?
On the server, the content is rendered (by Nunjucks):
<div id="header">{{headerHtml | safe}}</div>
(where headerHtml
is the output of render-to-string)
On the client, I'm then doing:
render((
<Header ... />
), document.querySelector('#header'));
And the header ends up being duplicated.
Hello,
There seems to be an issue with calling the render
function multiple times in the same file.
Example: I call the render
function on the server twice with the same app
but different data
:
-server.js-
render(<App data={1}>)
render(<App data={2}>)
but the render
function seem to always pass the data from the first render.
-app.js-
console.log(props.data)
// 1
// 1
I have tried many scenarios but still same results.
Thank You!
This library behaves differently than preact when dealing with undefined
prop values.
Expected behaviour:
preact-render-to-string
should behave like preact
:
MyComponent.defaultProps.someProp = 'X'
)undefined
is passed as prop value (<MyComponent someProp={undefined}/>
)console.log(this.props.someProp) >> 'X'
)Actual behaviour:
If undefined
is passed as prop value, then this.props.someProp
resolves to undefined
.
Here you can see how the implementation in preact
and preact-render-to-string
differ:
for (let i in defaultProps) {
if (props[i]===undefined) {
props[i] = defaultProps[i];
}
}
let defaultProps = vnode.nodeName.defaultProps,
props = assign({}, defaultProps || vnode.attributes);
if (defaultProps) assign(props, vnode.attributes);
Currently when you install preact (npm install preact
), [email protected] is installed.
However, when you install preact-render-to-string (npm install preact-render-to-string
), [email protected] is installed.
And version 5.0.0 is not compatible with [email protected], because of VNode format.
Please fix the default version when npm install preact-render-to-string
.
Thanks.
How to configure webpack for express template? I had an error with Babel syntax. 'SyntaxError: Unexpected token import'
As originally logged in preact-compat
: preactjs/preact-compat#126
I use glamor
for styling which renders data attributes for its css selectors. It looks like there was a change in v2.20.x
that removed the values of the data attributes. It now produces html as the following:
<div data-css-19swgx6 />
The server rendering tests in glamor
pass, so I assume that renderToStaticMarkup
from react-server/dom
renders the empty attributes, so it would be nice to have this as a little compatibility layer as well. Tracking this down, I was able to modify their tests to use render using this library and verified that the empty attributes weren't rendered, causing their tests to fail.
I've tracked it down to src/index.js#L137 which omits falsey values.
I am curious if this is an option you would consider adding? If so, I would be happy to submit a PR to add this as an opt-in feature.
I configured project as described in preact-compat
import React from 'react';
import render from 'preact-render-to-string';
import App from '../common/components/App.jsx';
import Container from '../common/components/Container.jsx';
export default function serverEntry() {
return render(
<Container>
<App />
</Container>
);
};
when run - error throws: ReferenceError: h is not defined
using 'import { h } from 'preact'' instead of 'import React from 'react'' - doesn't help
Components instantiated using React style (extends Component) and while aliasing React to point at react-compat render as [object Object]
. Reason being is that components instantiated using react-compat do not have a nodename
:
{ '$$typeof': Symbol(react.element),
type:
{ [Function: Footer]
childContextTypes: { intl: [Object], locale: [Object] },
displayName: 'Footer',
modulePath: '/app/components/Shared/Footer' },
key: null,
ref: null,
props:
{ store:
{ dispatch: [Function],
subscribe: [Function: subscribe],
getState: [Function: getState],
replaceReducer: [Function: replaceReducer] },
intl: { [Function] cache: [Object], toString: [Function], format: [Function] },
locale: 'en-CA',
dispatch: [Function] },
_owner: null }
Resulting in the following code being triggered in renderToString
:
if (!nodeName) {
return encodeEntities(vnode);
}
In addition to supporting componentDidCatch
(see #64) preact-render-to-string
should support static getDerivedStateFromError(error)
Documentation here: https://reactjs.org/docs/react-component.html#static-getderivedstatefromerror
The current hooks implementation rely on vnodes having a _component property. The property is created during rendering and is passed to the hooks implementation by options.render (used to be options.beforeRender).
Preact-render-to-string does not store the _component property, nor does it offer a way to pass it to the hooks implementation.
As a result preact-render-to-string fails when rendering components with hooks:
TypeError: Cannot read property '__H' of undefined
at f (.../node_modules/preact/hooks/dist/hooks.js:1:369)
at c (.../node_modules/preact/hooks/dist/hooks.js:1:465)
at exports.useState (.../node_modules/preact/hooks/dist/hooks.js:1:1235)
at HooksComponent (...)
at s (.../node_modules/preact-render-to-string/dist/index.js:1:1470)
Currently a fresh build fails (just cloned the repo):
$ npm run -s transpile && npm run -s transpile:jsx
node_modules/nan
resolve failed for "babel-runtime": Error: Cannot find module 'babel-runtime'
resolve failed for "babel-runtime": Error: Cannot find module 'babel-runtime'
node_modules/nan
resolve failed for "babel-runtime": Error: Cannot find module 'babel-runtime'
resolve failed for "babel-runtime": Error: Cannot find module 'babel-runtime'
Edit: Changed the title, because installing it via devDependencies
doesn't help.
The renderToString
function calls componentWillMount()
before rendering. However, per changes to React API, getDerivedStateFromProps
should take precedence over componentWillMount()
when available.
Preact already has an issue (preactjs/preact#1047) tracking what to do with React API changes.
Preact now supports getDerivedStateFromProps
per this PR - preactjs/preact#1094
I want to render KML using this, but I'm running into problems.
I have something like this
const folder = props => (
<Folder>
{props.children}
</Folder>
);
const KML = () => (
<kml>
<folder>
foo
</folder>
</kml>
);
What I want as output:
<kml>
<Folder>
foo
</Folder>
</kml>
What I get is:
<kml>
<folder>
foo
</folder>
</kml>
I passed xml: true
to renderToString
.
Is there a convention in the casing of JSX tags?
Hi!
Thanks for the package!
I have some problems withe the package - help me please.
I try to use to preact-render-to-string on server side to render component:
import { h } from 'preact';
const App = () => {
return <h1>App</h1>;
};
export default App;
import { h } from 'preact';
import render from 'preact-render-to-string';
import App from '../common/components/App.jsx';
const serverEntry = () => {
return render(<App />);
};
export default serverEntry;
import serverEntry from '../../serverEntry.js';
....
html = html.replace('<div id="app"></div>', serverEntry());
In my project I use to babel-env preset with target = 'node'.
When I add preact-render-to-string package to the project and try to transpile it with webpack - it breaks with error: 'Module build failed: Error: Couldn't find preset "es2015-minimal" relative to directory "D:\Projects\app1\node_modules\preact-render-to-string"'
It strange little bit....
so I add es2015-minimal to the project and again try to transpile, but now I get another warning:
node_modules\nan
resolve failed: { Error: Cannot find module 'caniuse-db'
at Function.Module._resolveFilename (module.js:472:15)
at Function.requireRelative.resolve (D:\Projects\app1\node_modules\require-relative\index.js:30:17)
at resolve (D:\Projects\app1\node_modules\modify-babel-preset\lib\serialize.js:26:26)
at findAndRemove (D:\Projects\app1\node_modules\modify-babel-preset\lib\serialize.js:83:11)
at D:\Projects\app1\node_modules\modify-babel-preset\lib\serialize.js:126:13
at Array.map (native)
at loadPreset (D:\Projects\app1\node_modules\modify-babel-preset\lib\serialize.js:118:29)
at module.exports (D:\Projects\app1\node_modules\modify-babel-preset\index.js:95:19)
at Object.<anonymous> (D:\Projects\app1\node_modules\babel-preset-es2015-minimal\index.js:5:18)
at Module._compile (module.js:573:32)
at Module._extensions..js (module.js:582:10)
at Object.require.extensions.(anonymous function) [as .js] (D:\Projects\app1\node_modules\babel-register\lib\node.js:152:7)
at Module.load (module.js:490:32)
at tryModuleLoad (module.js:449:12)
at Function.Module._load (module.js:441:3)
at Module.require (module.js:500:17)
at require (internal/module.js:20:19)
at D:\Projects\app1\node_modules\babel-core\lib\transformation\file\options\option-manager.js:302:17
at Array.map (native)
at OptionManager.resolvePresets (D:\Projects\app1\node_modules\babel-core\lib\transformation\file\options\option-manager.js:270:20)
at OptionManager.mergePresets (D:\Projects\app1\node_modules\babel-core\lib\transformation\file\options\option-manager.js:259:10)
at OptionManager.mergeOptions (D:\Projects\app1\node_modules\babel-core\lib\transformation\file\options\option-manager.js:244:14)
at OptionManager.init (D:\Projects\app1\node_modules\babel-core\lib\transformation\file\options\option-manager.js:374:12)
at File.initOptions (D:\Projects\app1\node_modules\babel-core\lib\transformation\file\index.js:216:65)
at new File (D:\Projects\app1\node_modules\babel-core\lib\transformation\file\index.js:139:24)
at Pipeline.transform (D:\Projects\app1\node_modules\babel-core\lib\transformation\pipeline.js:46:16)
at transpile (D:\Projects\app1\node_modules\babel-loader\lib\index.js:38:20)
at Object.module.exports (D:\Projects\app1\node_modules\babel-loader\lib\index.js:133:12)
at LOADER_EXECUTION (D:\Projects\app1\node_modules\loader-runner\lib\LoaderRunner.js:114:14)
at runSyncOrAsync (D:\Projects\app1\node_modules\loader-runner\lib\LoaderRunner.js:115:4) code: 'MODULE_NOT_FOUND' } caniuse-db
resolve failed: { Error: Cannot find module 'babel-runtime'
at Function.Module._resolveFilename (module.js:472:15)
at Function.requireRelative.resolve (D:\Projects\app1\node_modules\require-relative\index.js:30:17)
at resolve (D:\Projects\app1\node_modules\modify-babel-preset\lib\serialize.js:26:26)
at findAndRemove (D:\Projects\app1\node_modules\modify-babel-preset\lib\serialize.js:83:11)
at D:\Projects\app1\node_modules\modify-babel-preset\lib\serialize.js:126:13
at Array.map (native)
at loadPreset (D:\Projects\app1\node_modules\modify-babel-preset\lib\serialize.js:118:29)
at module.exports (D:\Projects\app1\node_modules\modify-babel-preset\index.js:95:19)
at Object.<anonymous> (D:\Projects\app1\node_modules\babel-preset-es2015-minimal\index.js:5:18)
at Module._compile (module.js:573:32)
at Module._extensions..js (module.js:582:10)
at Object.require.extensions.(anonymous function) [as .js] (D:\Projects\app1\node_modules\babel-register\lib\node.js:152:7)
at Module.load (module.js:490:32)
at tryModuleLoad (module.js:449:12)
at Function.Module._load (module.js:441:3)
at Module.require (module.js:500:17)
at require (internal/module.js:20:19)
at D:\Projects\app1\node_modules\babel-core\lib\transformation\file\options\option-manager.js:302:17
at Array.map (native)
at OptionManager.resolvePresets (D:\Projects\app1\node_modules\babel-core\lib\transformation\file\options\option-manager.js:270:20)
at OptionManager.mergePresets (D:\Projects\app1\node_modules\babel-core\lib\transformation\file\options\option-manager.js:259:10)
at OptionManager.mergeOptions (D:\Projects\app1\node_modules\babel-core\lib\transformation\file\options\option-manager.js:244:14)
at OptionManager.init (D:\Projects\app1\node_modules\babel-core\lib\transformation\file\options\option-manager.js:374:12)
at File.initOptions (D:\Projects\app1\node_modules\babel-core\lib\transformation\file\index.js:216:65)
at new File (D:\Projects\app1\node_modules\babel-core\lib\transformation\file\index.js:139:24)
at Pipeline.transform (D:\Projects\app1\node_modules\babel-core\lib\transformation\pipeline.js:46:16)
at transpile (D:\Projects\app1\node_modules\babel-loader\lib\index.js:38:20)
at Object.module.exports (D:\Projects\app1\node_modules\babel-loader\lib\index.js:133:12)
at LOADER_EXECUTION (D:\Projects\app1\node_modules\loader-runner\lib\LoaderRunner.js:114:14)
at runSyncOrAsync (D:\Projects\app1\node_modules\loader-runner\lib\LoaderRunner.js:115:4) code: 'MODULE_NOT_FOUND' } babel-runtime
What is wrong?
Thanks
P.S. you can reproduce it https://github.com/budarin/app
I still encounter this issue with hooks: #72 specifically with webpack.
Seems to be a mjs issue, since using this fixes it: https://github.com/lukeed/webpack-modules
Does this same thing done in preact need to happen here too? preactjs/preact#1425
Rendering components using createContext fails.
Consumer components does not receive the context set in the Provider component.
renderToString
should check if there's a contextType and a corresponding context.
Credit goes to @kristoferbaxter for finding this:
<select value={2}>...</select>
will output an attribute on the select, not on the correct option. The spec has this to say about values on a <select>
-element:
The value IDL attribute, on getting, must return the value of the first option element in the list of options in tree order that has its selectedness set to true, if any. If there isn't one, then it must return the empty string.
On setting, the value attribute must set the selectedness of all the option elements in the list of options to false, and then the first option element in the list of options, in tree order, whose value is equal to the given new value, if any, must have its selectedness set to true and its dirtiness set to true.
So we need to set the selected
property on the correct <option>
child.
Our builds are failing because preact-jsx-chai
is using preact-render-to-string
with a ^3.x
dependency. With the change in 3.8.0 to no longer cooerce node names to a String before calling the match function here 46e72e9#diff-1fdf421c05c1140f6d71444ea2b27638L162, any node that does not have a node name now fails the unit test with an exception like:
PhantomJS 2.1.1 (Mac OS X 0.0.0)
undefined is not an object (evaluating 'y.match')
p@webpack:///~/preact-render-to-string/dist/jsx.js:1:2667 <- setup-unit.js:4350:141
p@webpack:///~/preact-render-to-string/dist/jsx.js:1:1643 <- setup-unit.js:4326:34
p@webpack:///~/preact-render-to-string/dist/jsx.js:1:1643 <- setup-unit.js:4326:34
exports@webpack:///~/preact-render-to-string/dist/jsx.js:1:8303 <- setup-unit.js:4455:11
doRender@webpack:///~/preact-jsx-chai/dist/index.js:65:0 <- setup-unit.js:4039:50
webpack:///~/preact-jsx-chai/dist/index.js:80:0 <- setup-unit.js:4054:25
/Users/bneff/repos/sports-widget/node_modules/chai/chai.js:5341:38
webpack:///tests/unit/components/scoreboard/event.js:311:39 <- unit/components/scoreboard/event.js:7005:57
I would recommend adding the cooercion back in to a 3.8.1 release and removing it in a 4.0 release if you really want to take it out.
I've got this error when I launch my node server :
content: render(<App/>)
^
SyntaxError: Unexpected token <
at createScript (vm.js:53:10)
at Object.runInThisContext (vm.js:95:10)
at Module._compile (module.js:543:28)
at Object.Module._extensions..js (module.js:580:10)
at Module.load (module.js:488:32)
at tryModuleLoad (module.js:447:12)
at Function.Module._load (module.js:439:3)
at Module.runMain (module.js:605:10)
at run (bootstrap_node.js:425:7)
at startup (bootstrap_node.js:146:9)
Here's a sample of my server.js file (didn't show all the requires for instance).
I don't know what's wrong.
You can see I use preact-render-to-string
and pass this rendering to my handlebar template.
The same technique is used there : https://github.com/jakearchibald/big-web-quiz/blob/master/server/views.js
const handlebars = require('handlebars');
const render = require('preact-render-to-string');
const index = require('../front/index');
/** @jsx h */
app.get('/', (req, res) => {
res.send(index({
css: ['/static/style.css'],
lazyCss: ['/static/style.css'],
scripts: ['/static/build.js'],
content: render(<App/>)
}));
});
preactjs/preact#819 adds support for componentDidCatch(error)
(note that it currently does not include the info
argument)
we will need to support componentDidCatch(error)
to achieve parity with preact
once that PR is merged in
Note that the preact
PR preactjs/preact#819 does not include support for static getDerivedStateFromError(error)
Documentation here: https://reactjs.org/docs/react-component.html#static-getderivedstatefromerror
Not sure if this an issue or a clarification.
If I have some SVG, such as
<path d="M 2 50 A 48 48 0 0 1 50 2" stroke="#gradLeft-1" strokeWidth="4" fill="none" />
It doesn't work correctly.
If I change 'strokeWidth' to 'stroke-width' (changed to lower case with a dash) then it does work ok.
This is different to react.
Is this behaviour correct? or have I done something wrong?
I'm integrating preact-compat
into create-react-app
without ejecting and had quite a lot of success doing it so far.
For the Jest tests, I managed to use moduleNameMapper
to use the preact-*
testing utilities instead of anything from React, something similar to this:
{
'^react-dom/server$': '<rootDir>/node_modules/preact-render-to-string/dist/index.js',
'^react-dom/test-utils$': '<rootDir>/node_modules/preact-test-utils/lib/index.js',
'^react-dom$': '<rootDir>/node_modules/preact-compat-enzyme/lib/index.js',
'^react-test-renderer/shallow$': '<rootDir>/node_modules/preact-test-utils/lib/index.js',
'^react-test-renderer$': '<rootDir>/node_modules/preact-test-utils/lib/index.js',
'^react-addons-test-utils$': '<rootDir>/node_modules/preact-test-utils/lib/index.js',
'^react-addons-transition-group$': '<rootDir>/node_modules/preact-transition-group/dist/preact-transition-group.js',
'^react$': '<rootDir>/node_modules/preact-compat-enzyme/lib/index.js'
}
While running the Jest tests, I've run into an issue when using renderToJsxString
directly to expect(renderToJsxString(<SomeComponent></SomeComponent>)).toMatchSnapshot();
there are __source
and __self
attributes on every component in the output.
The output looks similar to this:
<div
__source={
Object {
"fileName": "<some-path-here>/src/components/mainframe/MainFrame.js",
"lineNumber": 9
}
}
>
<cl
src=""
id="main-app-iframe"
__source={
Object {
"fileName": "<some-path-here>/src/components/mainframe/MainFrame.js",
"lineNumber": 10
}
}
class="tst-app-frame"
>
</cl>
</div>
I managed to fix this by supplying my own attributeHook
, but it means that I needed to recreate all of the functionality from within which is not the best for keeping in sync with updates.
This is all I wanted to add inside attributeHook
if (name === '__source' || name === '__self') {
return '';
}
The opts
I'm passing to renderToJsxString
are:
{
jsx: true,
xml: false,
functions: true,
functionNames: true,
skipFalseAttributes: false,
pretty: ' ',
shallow: true,
min: true,
attributeHook // the one mentioned above
}
I'm not sure if this is by design, or something that only happens with preact-compat
or if it's related to me using the moduleNameMapper
setup written above.
The solution could be to have a switch to filter for these fields, it could be to have a blacklist of attributes or it could be that there's an error on my part.
Can you help to figure it out?
This may be under the preact-compat
domain but relates directly to rendering on the server.
React calls componentWillMount
on components when server rendering which some libraries depend upon e.g. isomorphic-style-loader. Is this something you'd consider supporting?
Background facebook/react#2674
Hi,
Boolean attribute rendering seems to differ from Preact itself (4.8.0 at least).
For example with the JSX:
<div aria-hidden={true} />
preact: <div aria-hidden="true"></div>
preact-render-to-string: <div aria-hidden></div>
http://jsfiddle.net/28ckgyzj/1/ (see console log)
(With ARIA attributes presence doesn't indicate truth as it does with the checked attribute for example).
Thanks
Currently the behaviour for void elements (img
, br
, etc) is that they render without a closing /
– for example, <br>
instead of <br/>
.
Unfortunately this closing /
is required for XHTML, meaning a Preact render won't validate against that content type. It's also a possible compatibility issue when using preact-compat
, since React's own renderToString
method adds the /
.
The /
is optional in HTML5, so I think rendering it out should resolve the above issues without breaking anything.
If this looks like a good idea, I'd be happy to submit a PR.
Thanks!
Currently a string is thrown instead of an error at: https://github.com/developit/preact-render-to-string/blob/ef7b0a260f3bf834a7deaf4cb5e8016610c57ed4/src/index.js#L149-L150
This leads to very uninformative lines such as:
<[object Object] cars="[object Object],[object Object],[object Object],[object Object]">
Is there a reason why a proper error is not thrown?
Bundling preact-render-to-string
together with preact/compat
results in duplicated (?) preact
instead of reusing the preact/compat
(if that's at all possible).
Most likely caused by peerDep being preact
and not preact/compat
.
Test case:
npm i browserify preact@latest preact-render-to-string@latest
bundling with base preact
→ size 12642
const Browserify = require("browserify");
const { Readable, Writable } = require("stream");
let len = 0;
Browserify(new Readable({
read () {
this.push(`
require("preact");
require("preact-render-to-string");
`);
this.push(null);
}
}))
.bundle()
.pipe(new Writable({
write (chunk, enc, next) {
len += chunk.toString().length;
next();
}
}))
.on("finish", () => console.log("size:", len));
bundling with preact/compat
→ size 19721
const Browserify = require("browserify");
const { Readable, Writable } = require("stream");
let len = 0;
Browserify(new Readable({
read () {
this.push(`
require("preact/compat");
require("preact-render-to-string");
`);
this.push(null);
}
}))
.bundle()
.pipe(new Writable({
write (chunk, enc, next) {
len += chunk.toString().length;
next();
}
}))
.on("finish", () => console.log("size:", len));
As far as I know, React.renderToString()
never calls the componentDidMount()
lifecycle hook, as the code in that hook (I would think almost always) only needs to run on the client for inserting various functionality into the view.
I had some calls to window
within some of my components' compontentDidMount()
hook to add an event here and there, and when crossing over and using preact-compat
and I've been getting errors because Node obviously doesn't have access to the browser's window
global variable.
It seems DOM events are not working when using preact-render-to-string
.
import { render } from 'preact-render-to-string';
import {h, Component} from 'preact';
class Page extends Component {
click(event) {
console.log(event);
}
render(){
return <button onClick={this.click}>Click me!</button>
}
}
const html = render(<Page />);
console.log(html);
// <button>Click me!</button>
Preact Version: 8.4.2
PreactRenderToString Version: 4.1.0
This repo is missing a license. Without a license, all code is copyright the author and may not be used by anyone else.
Please use something like http://choosealicense.com/ to decide what license to use. I recommend MIT or GPL.
I guess it may be something to do with this Preact commit: preactjs/preact@a5b286b
With Preact 5.6.0:
http://jsfiddle.net/28ckgyzj/3/
With Preact 5.2.0-beta.0:
http://jsfiddle.net/5tzxLy7d/2/
All components currently being ab-tested just end up rendering [object Object]. This only happens on the server side, so it's not a problem with preact
Is this known already? (and is there a workaround?) It appears to be the only thing blocking me from using preact
This works correctly in preact proper
Just noticed, that the jsx renderer double closes self closing tags like meta
or base
.
Test case:
const render = require("preact-render-to-string/jsx");
const html = <html><head><base href="foo/" /></head></html>;
console.log(render(html));
// Logs:
// <html>
// <head>
// <base href="foo/" /></base>
// </head>
// </html>
@developit it would be amazing it we could ship a new 5.x version with those latest fixes.
Thank you.
I found this issue whilst comparing snapshots made with jest with and without coverage. When --coverage adds the istanbul babel plugin it adds random elements to the output.
I made a repo where you can see this in action: https://github.com/PepijnSenders/istanbul-preact-render-spy-bug
The output of this command is empty: find node_modules/preact-render-to-string -type f -name '*.ts'
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.