onClick handler not registering with ReactDOMServer.renderToString
Solution 1
React DOM render to string only sends the initial HTML as a string without any JS.
You need a client side react router as well which will attach the required JS handlers to the HTML based on their react-id's. The JS needs to run on both sides.
Universal rendering boilerplate for quick start. https://github.com/erikras/react-redux-universal-hot-example
Another question which is similar to yours. React.js Serverside rendering and Event Handlers
Solution 2
None of the hooks will register with ReactDOMServer.RenderToString. If you want to accomplish server side rendering + hooks on your react component, you could bundle it on the client (webpack, gulp, whatever), and then also use ReactDOMServer.RenderToString on the server.
Here's a blog post that helped me accomplish this: https://www.terlici.com/2015/03/18/fast-react-loading-server-rendering.html
Alexander Mills
Dev, Devops, soccer coach. https://www.github.com/oresoftware
Updated on June 06, 2022Comments
-
Alexander Mills almost 2 years
I am trying to copy this fiddle: http://jsfiddle.net/jhudson8/135oo6f8/
(I also tried this example http://codepen.io/adamaoc/pen/wBGGQv and the same
onClick
handler problem exists)and make the fiddle work for server side rendering, using
ReactDOMServer.renderToString
I have this call:
res.send(ReactDOMServer.renderToString(( <html> <head> <link href={'/styles/style-accordion.css'} rel={'stylesheet'} type={'text/css'}></link> </head> <body> <Accordion selected='2'> <AccordionSection title='Section 1' id='1'> Section 1 content </AccordionSection> <AccordionSection title='Section 2' id='2'> Section 2 content </AccordionSection> <AccordionSection title='Section 3' id='3'> Section 3 content </AccordionSection> </Accordion> </body> </html> )));
the Accordion element looks like so:
const React = require('react'); const fs = require('fs'); const path = require('path'); const Accordion = React.createClass({ getInitialState: function () { // we should also listen for property changes and reset the state // but we aren't for this demo return { // initialize state with the selected section if provided selected: this.props.selected }; }, render: function () { // enhance the section contents so we can track clicks and show sections const children = React.Children.map(this.props.children, this.enhanceSection); return ( <div className='accordion'> {children} </div> ); }, // return a cloned Section object with click tracking and 'active' awareness enhanceSection: function (child) { const selectedId = this.state.selected; const id = child.props.id; return React.cloneElement(child, { key: id, // private attributes/methods that the Section component works with _selected: id === selectedId, _onSelect: this.onSelect }); }, // when this section is selected, inform the parent Accordion component onSelect: function (id) { this.setState({selected: id}); } }); module.exports = Accordion;
and the AccordionSection component looks like so:
const React = require('react'); const AccordionSection = React.createClass({ render: function () { const className = 'accordion-section' + (this.props._selected ? ' selected' : ''); return ( <div className={className}> <h3 onClick={this.onSelect}> {this.props.title} </h3> <div className='body'> {this.props.children} </div> </div> ); }, onSelect: function (e) { console.log('event:',e); // tell the parent Accordion component that this section was selected this.props._onSelect(this.props.id); } }); module.exports = AccordionSection;
everything works, and the CSS is working, but the problem is that the onClick doesn't get registered. So clicking on the accordion elements does nothing. Does anyone know why the onClick handler might not get registered in this situation?
-
Jeff P Chacko about 8 yearsis JS working at all? is any of the JS working on client?
-
Alexander Mills about 8 yearsI think the missing piece is that on the client once the markup gets there we need to make some more React calls that actually bind the handlers
-