How render React on server to callback function? - reactjs

I want render react-app on server with full lifecycle and updates supports.
Like https://github.com/Yomguithereal/react-blessed, but not to terminal, to callback-function.
Example, pseudo-code:
render(<MyComponent />, (tree)=>{
console.log(tree); // new react component-tree
})
Another example, https://github.com/iamdustan/react-hardware
https://github.com/facebook/react/blob/077d660a2727e3d3d6629d3a62693f8509100139/src/renderers/testing/ReactTestRenderer.js#L138

I believe you are looking to implement a "custom renderer" for react. Here's an article that I found that could be helpful:
http://goshakkk.name/react-custom-renderers/

Related

Can I live preview React components in VSCode?

New to React. I have been using live server for html files in VS Code but I can't seem to find the same functionality for React components (.js files). Maybe it's obvious or I'm looking for the wrong thing.
I'd like to make changes in the component, especially MUI styling and see the incremental results in a live preview, rather than the entire application having to refresh and click back to the form I'm working on. Any thoughts or suggestions? Thanks.
You don't have to change your code when using storybook. You just have to write new files, that import your component. Then you can pass it fake props to see how it behave depending in many scenarios. If you use create-react-app, it super easy to install, if you have your own config, then your level is good enough to follow their tutorial. The files are formatted like this: MyComponent.stories.js . Then storybook will look at all files that contains "stories" in their name, and launch them on port 6006 when you write yarn/npm run storybook in your terminal. I highly recommend storybook, it is used by most of companies.
Couldn't find a satisfactory solution and not willing to invest too much. Storybook looks like I'd have to change my code and because I'm still relatively new to react, not sure I'm up for that.
I'm just letting VSCode restart server each time I save a change then going to the browser and clicking through the menus to get to the page I'm working on.
For more complex ui changes, I'll create a code sandbox mini react app and just work on that for, like css changes, etc.
UPDATE:
I've implemented Storybook and I like it. After following the doc to install it I saw that I just needed to create a file (story) for a component like MyComponent.stories.js and put in the few lines of code to import and use it, passing in whatever props I wanted to see.
I decided to put my stories files into a separate separate stories folder under src. Here's an example for a Details component:
import React from 'react';
import { action } from '#storybook/addon-actions';
import Details from '../Details';
// How to display the component in Storybook page
export default {
title: 'Details',
component: Details,
// Our exports that end in "Data" are not stories.
excludeStories: /.*Data$/
};
// Props passed into component
export const recordData = {
record: {
id: '1',
createdOn: '2020-04-20 4:07 PM',
createdBy: 'dgarv',
modifiedOn: '2020-04-20 4:07 PM',
modifiedBy: 'dgarv',
}
};
// Use the actual component
export const Default = () => <Details {...recordData} />;
I've developed an extension named AutoPreview that you can use it to preview React/Vue component in VS Code.
You can get it in extension market: https://marketplace.visualstudio.com/items?itemName=jawei.autopreviewer&ssr=false#overview
You can use Preview.js to see the rendered code - https://previewjs.com/docs/platforms/vscode

How to perform a server side data fetching with React Hooks

We just start moving into React Hooks from the React life-cycle and one of the things that we noticed, is that there's no straightforward way to run something similar to ComponentWillMount for loading data before sending the rendered page to the user (since useEffect is not running on SSR).
Is there any easy way supported by React to do so?
I had the same problem. I've managed to solve it with a custom hook and by rendering application twice on the server-side. The whole process looks like this:
during the first render, collect all effects to the global context,
after first render wait for all effects to resolve,
render the application for the second time with all data.
I wrote an article with examples describing this approach.
This is a direct link to the example form article on CodeSandbox.
Also, I have published an NPM package that simplifies this process - useSSE on GitHub.
This is a little tricky but one way around is to do the fetch directly in the component as in
function LifeCycle(props){
console.log("perform the fetch here as in componentwillmount")
const [number, setNumber] = useState(0)
useEffect(() => {
console.log("componentDidMount");
return () => {
console.log("componentDidUnmount");
};
}, []);
}

Using this.props.history.push("/path") is re-rendering and then returning

Edited the question after further debugging
I am having a strange issue, tried for a while to figure it out but I can't.
I have a React Component called NewGoal.jsx, after a user submits their new goal I attempt to reroute them to my "goals" page.
The problem: After they submit the browser loads in my goal page, but only for one second. It then continues and goes BACK to the NewGoal page!!
I am trying to understand why this is happening, I am beginning to feel that this might be an async issue.
Here is my code, currently it is using async-await, I also tried the same idea using a .then() but it also didn't work:
async handleSubmit(event)
{
const response = await axios.post("http://localhost:8080/addGoal",
{
goalID: null,
duration: this.state.days,
accomplishedDays: 0,
isPublic: this.state.isPublic,
description: this.state.name,
dateCreated: new Date().toISOString().substring(0,10),
}) */
// push to route
this.props.history.push("/goals");
}
While debugging, I tried taking out the functionality where I post the new message, and just did a history.push, code is below - and this completely worked.
// THIS WORKS
async handleSubmit(event)
{
// push to route
this.props.history.push("/goals");
}
But as soon as I add anything else to the function, whether before the history.push or after, it stops working.
Any advice would be very very appreciated!
Thank you
In the React Router doc's the developers talk about how the history object is mutable. Their recommendation is not to alter it directly.
https://reacttraining.com/react-router/web/api/history#history-history-is-mutable
Fortunately there are few ways to programmatically change the User's location while still working within the lifecycle events of React.
The easiest I've found is also the newest. React Router uses the React Context API to make the history object used by the router available to it's descendents. This will save you passing the history object down your component tree through props.
The only thing you need to do is make sure your AddNewGoalPage uses the history object from context instead of props.
handleSubmit(event)
...
//successful, redirect to all goals
if(res.data)
{
this.context.history.push("/goals")
}
...
})
}
I don't know if you're using a class component or a functional component for the AddNewGoalPage - but your handleSubmit method hints that it's a member of a Class, so the router's history object will be automatically available to you within your class through this.context.history.
If you are using a functional component, you'll need to make sure that the handleSubmit method is properly bound to the functional component otherwise the context the functional component parameter is given by React won't not be available to it.
Feel free to reply to me if this is the case.

more extensive example implementation code for react-pouchdb-changes

I'm brand new to both pouchdb and react. I found the react-pouchdb-changes module which seems exactly like what I want to be using.
However, the example code it provides is far too sparse - I'm really at a loss as to how it would be incorporated into a basic react application.
Can someone provide a more complete example usage with some basic explanations of what each piece does?
This module seems to be merely a wrapper for the changes method. You can get a live example here. The link comes right from the documentation.
If that's not enough info you can check out the API reference with examples and example responses.
It's up to you how you want react-pouchdb-changes to integrate with React. All it does is provide you with a component to put your onChange handler on. These parts of the code example are the relevant ones:
<PouchDBChanges
…
onChange={change => console.log(change) /* do something useful with the change here instead of just logging it! */}
>
{/* your <App> component here */}
</PouchDBChanges>
Just use the component in your JSX code (wrap your main component or any container component with it).
If you have difficulties with setting up a React example, try using create-react-app. You'll have a running React app within a few seconds. A good place to add your <PouchDBChanges> component would be src/App.js - just wrap the outermost <div> with the component.

Multiple instances of same react component

I want to add a react component, a comments feature, to a non-react site.
The site has a news page with infinite scrolling. Under each news story I want to include the react comments component. I plan to model it after the FB tutorial here: http://facebook.github.io/react/docs/tutorial.html
My question is, how do I dynamically mount each React component to a DOM story element? Basically, I want to have many instances of the same react comments component, but with each instance tied to a unique story (div).
I think I need to render the react component on the server side, where I can dynamically set the React.renderComponent. Any pointers/examples appreciated.
When the post is added you need to have your data and the target dom node (we'll call these variables data and el)
React.render(<MyComponent data={data} />, el);
Or without JSX
React.render(React.createElement(MyComponent, {data: data}), el);
To clean up:
React.unmountComponentAtNode(el);
For server side rendering you can do:
React.renderToString(React.createElement(MyComponent, {data: data}))
and as long as the result of that ends up as el on the client, you can mount it with React.render as mentioned above.

Resources