ReactTable and custom server side data update - reactjs

Has anybody ever used this awesome react components processing server side data?
The solution given here is excellent if you don't need to manually update the data.
I would need to refresh the data not only when changing page/pageSize/sorting/filtering, but also after some intervalled time, to see if data got changed.
Also I have an extension of the table that allows the user to do a full text search on all columns so I would need to update the data when the user changes the content of the custom search box too.

I had the same problem as yours and I started looking for asynchronous tests with ReactJs and I found this article that was very useful. The key part was to use "update" method on the Enzyme component, like below:
const items = ['die Straße', 'die Adresse', 'die Nationalität'];
jest.useFakeTimers();
describe('<DelayedList />', () => {
test('it renders the items with delay', () => {
const component = shallow(
<DelayedList items={items} />
);
jest.runAllTimers();
component.update(); // <--- force re-render of the component
expect(component.state().currentIndex).toEqual(items.length);
expect(component).toMatchSnapshot();
});
For more information, see this medium article.

Related

Algolia: Export React Instant Search results

Is there any way to export Algolia's React Instant Search results to a CSV? I've tried using the react-csv package, but it doesn't work with Algolia's Hit Component. The package requires data as props, but the data is constantly changing since it's React Instant Search.
What I mean by constantly changing is that on page load, you're given the entire index of records found, then you can narrow down the results with the search bar or other filtering components.
I've gone down the Google rabbit hole looking for information about exporting Algolia's search results as a CSV, but I haven't found anything regarding React Instant Search—unless I completely missed it.
Has anyone tried this before? If so, could you point me in the right direction regarding documentation or examples?
Not sure if this solves your problem but one possible way is to use the StateResults widget. The StateResults widget provides a way to access the searchState and the searchResults of InstantSearch.
Here I will create a custom StateResults component in the form of a download button and then connect it using the connectStateResults connector.
I have attached a demo below as well.
For simplicity I didn't format the data to be fed into the CSV builder.
// 1. Create a React component
const StateResults = () => {
// return the DOM output
};
// 2. Connect the component using the connector
const CustomStateResults = connectStateResults(StateResults);
// 3. Use your connected widget
<CustomStateResults />
In your case something like
const StateResults = ({ searchResults }) => {
const hits = searchResults?.hits;
return (
<div>
<button>{hits && <CSVLink data={hits}>Download CSV</CSVLink>}</button>
</div>
);
};
const DownloadButton = connectStateResults(StateResults);
//in your JSX then <DownloadButton />

ReactJs : How to print data from console to web-page?

After a successful POST and GET query, the results of my operation are visible in the console of my React Dev Tools. How should I take those results, preferable create a table and render that table on my web-app itself?
Here is the GET request :
axios.get('http://localhost:5000/result')
.then((response) => {
console.log(response);
});
}
The format of results displayed on console is like this :
Let's say I want to create a table by traversing through the results with headers _id and Name. I know I should use the map function. But exactly where and how should I do that in my code?
You have a few options. You can make your call in componentDidMount, set the result in a state and then render that state.
componentDidMount() {
axios.get('http://localhost:5000/result')
.then((response) => {
this.setState({
data: response // maninpulate your response here
})
});
}
}
render() {
const { data } = this.state;
return this.renderTable(data) // this should return a table
}
Assuming you know the concept of 'useState' in react hooks. If not please have an understanding of it.
Long story short, useState is used to store the data in variables.
const [data, setData] = useState();
Instead of console.log(response); you set the response to the variable i.e; setData(response);
In html,
<table>
//some headers, if needed
//This will iterate your array of objects
{data.map((eachData) => (
<tr> <td>{eachData.id}</td>
<td>{eachData.name}</td>
....
</tr>
)
</table>
Please Note: The HTML part works for both class-based and function-based React components where as 'useState' is part of React hooks functionality, works only for function-based components.
I have created a small sample app where I have used react-table for displaying the data as a table. Also In this example I have added promise in order to simulate server fetching data from server. This you can replace with actual server call i.e., axis.get etc.
React-table provides a lot many features that might be helpful. Such as you can provide which columns you wish to display out of all the columns from the data.
If you do not wish to use any library for displaying table, that is also possible only that you have to replace ReactTable with your custom table implementation.
Hope this helps.
Thanks to this page: https://www.skptricks.com/2019/02/can-you-consolelog-in-jsx.html.
You can do console.log in the render function of a class component or in the return statement of a function component. In your case:
function Foo(props){
data = axios.get('http://localhost:5000/result')
return(
<>
{console.log(data)}
</>)
}
In my opinion, it's much more straight forward than the other state methods.

Will ReactDOM.hydrate() trigger lifecycle methods on the client?

From the React 16 docs about ReactDOM.hydrate(),
Same as render(), but is used to hydrate a container whose HTML contents were rendered by ReactDOMServer. React will attempt to attach event listeners to the existing markup.
Will ReactDOM.hydrate() also trigger lifecycle methods on the client such as componentWillMount(), componentDidMount() during initial render?
Will render() method be called on the client during hydration? I suppose not, because that's the difference between ReactDOM.render() and ReactDOM.hydrate()?
If render method won't be called on the client, we wouldn't expect componentDidMount() lifecycle method to be triggered.
If none of the lifecycle methods are called on the client, how would we know when has React finished rendering. I suppose the callback in the following syntax:
ReactDOM.hydrate(element, container[, callback])
I want to understand if there are lifecycle methods / hooks (which give more control over the application) available when React is "attempting to attach event listeners to existing markup".
Since ReactDOM.hydrate is (and should be) called on the client then YES it is supposed to run componentDidMount. componentWillMount is already called when rendered on the server.
componentDidMount does not run on the server, therefore when you call hydrate, the app runs the event.
Think about hydrate as a different render method. It does render but not in the same way. It looks for mismatches between your server rendered React and your client React. It does not render everything again.
React expects that the rendered content is identical between the server and the client. It can patch up differences in text content (such as timestamps), but you should treat mismatches as bugs and fix them
However you might want to do some crazy stuff like rendering something completely different on the client side (than what was rendered on the server). For this pay attention to this paragraph
If you intentionally need to render something different on the server and the client, you can do a two-pass rendering. Components that render something different on the client can read a state variable like this.state.isClient, which you can set to true in componentDidMount(). This way the initial render pass will render the same content as the server, avoiding mismatches, but an additional pass will happen synchronously right after hydration. Note that this approach will make your components slower because they have to render twice, so use it with caution.
So as you can see it does a render pass. If there are no mismatches React is optimized for that.
I hope it was clarifying. I speak from experience with React SSR and basic understanding of reading the docs.
The rendered elements probably aren't same between server and client, because initially the elements are rendered into texts at the server in memory, therefore they are not mounted. When the content is moved to client, it can be re-attached to react via hydrate which is fake "render" to wire with the rest of react functionalities, such as events.
In order to tell when it's hydated, here's a piece from internet which I found clearly stated the above rational. https://dev.to/merri/understanding-react-ssr-spa-hydration-1hcf?signin=true
const HydrateContext = createContext('hydrated')
export function useIsHydrated() {
return useContext(HydrateContext)
}
export function IsHydratedProvider({ children }) {
const [isHydrated, setIsHydrated] = useState(false)
useEffect(() => {
setIsHydrated(true)
}, [])
return (
<HydrateContext.Provider value={isHydrated}>
{children}
</HydrateContext.Provider>
)
}
To use it,
function MyComponent() {
const isHydrated = useIsHydrated()
return !isHydrated ? 'Initial render' : 'SPA mode'
}
function App() {
return (
<IsHydratedProvider>
<MyComponent />
</IsHydratedProvider>
)
}
It feels to me, any rendered component teleports from the server to the client.
p.s Here's another article which talks about the second render after the mount, https://medium.com/swlh/how-to-use-useeffect-on-server-side-654932c51b13
I read the type of ReactDOM.hydrate in TypeScript system:
(
element: SFCElement<any> | Array<SFCElement<any>>,
container: Container| null,
callback?: () => void
): void;
And example to the above declaration:
ReactDOM.hydrate(
<App />, // element
document.getElementById('root'), // container
() => { // callback
/* do what you want after hydration */
}
);

I am using Redux. Should I manage controlled input state in the Redux store or use setState at the component level?

I have been trying to figure out the best way to manage my react forms. I have tried to use the onChange to fire an action and update my redux store with my form data. I have also tried creating local state and when my form gets submitted I trigger and action and update the redux store.
How should i manage my controlled input state?
I like this answer from one of the Redux co-authors:
https://github.com/reactjs/redux/issues/1287
Use React for ephemeral state that doesn't matter to the app globally
and doesn't mutate in complex ways. For example, a toggle in some UI
element, a form input state. Use Redux for state that matters globally
or is mutated in complex ways. For example, cached users, or a post
draft.
Sometimes you'll want to move from Redux state to React state (when
storing something in Redux gets awkward) or the other way around (when
more components need to have access to some state that used to be
local).
The rule of thumb is: do whatever is less awkward.
That is, if you're sure that your form won't affect global state or need to be kept after your component is unmounted, then keep in the react state.
You can use the component's own state. And then take that state and give it as an argument to the action. That's pretty much the "React way" as described in the React Docs.
You can also check out Redux Form. It does basically what you described and links the form inputs with Redux State.
The first way basically implies that you're doing everything manually - maximum control and maximum boilerplate. The second way means that you're letting the higher order component do all the work for you. And then there is everything in between. There are multiple packages that I've seen that simplify a specific aspect of form management:
React Forms -
It provides a bunch of helper components to make form rendering and validation more simple.
React JSON schema -
Allows one to build an HTML form from a JSON schema.
Formsy React -
As the description says: "This extension to React JS aims to be that "sweet spot" between flexibility and reusability."
Update: seems these days Redux Form is being replaced with:
React Final Form
And one more important contender in the space that's worth checking out is:
Formik
Tried out React Hook Form in my last project - very simple, small footprint and just works:
React Hook Form
TL;DR
It's fine to use whatever as it seems fit to your app (Source: Redux docs)
Some common rules of thumb for determing what kind of data should be
put into Redux:
Do other parts of the application care about this data?
Do you need to be able to create further derived data based on this original data?
Is the same data being used to drive multiple components?
Is there value to you in being able to restore this state to a given point in time (ie, time travel debugging)?
Do you want to cache the data (ie, use what's in state if it's already there instead of re-requesting it)?
These questions can easily help you identify the approach that would be a better fit for your app. Here are my views and approaches I use in my apps (for forms):
Local state
Useful when my form has no relation to other components of the UI. Just capture data from input(s) and submits. I use this most of the time for simple forms.
I don't see much use case in time-travel debugging the input flow of my form (unless some other UI component is dependent on this).
Redux state
Useful when the form has to update some other UI component in my app (much like two-way binding).
I use this when my form input(s) causes some other components to render depending on what is being input by the user.
Personally, I highly recommend keeping everything in the Redux state and going away from local component state. This is essentially because if you start looking at ui as a function of state you can do complete browserless testing and you can take advantage of keeping a reference of full state history (as in, what was in their inputs, what dialogs were open, etc, when a bug hit - not what was their state from the beginning of time) for the user for debugging purposes. Related tweet from the realm of clojure
edited to add: this is where we and our sister company are moving in terms of our production applications and how we handle redux/state/ui
Using the helper libraries is just more quick and avoid us all the boilerplate. They may be optimized, feature rich ...etc. As they make all different aspects more of a breeze. Testing them and making your arsenal as knowing what's useful and better for the different needs, is just the thing to do.
But if you already implemented everything yourself. Going the controlled way. And for a reason you need redux. In one of my projects. I needed to maintain the form states. So if i go to another page and come back it will stay in the same state. You only need redux, if it's a mean for communicating the change to multiple components. Or if it's a mean to store the state, that you need to restore.
You need redux, if the state need to be global. Otherwise you don't need it. For that matter you can check this great article here for a deep dive.
One of the problems that you may encounter! When using the controlled inputs. Is that you may just dispatch the changements at every keystroke. And your form will just start freezing. It became a snail.
You should never directly dispatch and use the redux flux, at every changement.
What you can do, is to have the inputs state stored on the component local state. And update using setState(). Once the state change, you set a timer with a delay. It get canceled at every keystroke. the last keystroke will be followed by the dispatching action after the specified delay. (a good delay may be 500ms).
(Know that setState, by default handle the multiple successive keystroke effectively. Otherwise we would have used the same technique as mentioned above (as we do in vanilla js) [but here we will rely on setState])
Here an example bellow:
onInputsChange(change, evt) {
const { onInputsChange, roomId } = this.props;
this.setState({
...this.state,
inputs: {
...this.state.inputs,
...change
}
}, () => {
// here how you implement the delay timer
clearTimeout(this.onInputsChangeTimeoutHandler); // we clear at ever keystroke
// this handler is declared in the constructor
this.onInputsChangeTimeoutHandler = setTimeout(() => {
// this will be executed only after the last keystroke (following the delay)
if (typeof onInputsChange === "function")
onInputsChange(this.state.inputs, roomId, evt);
}, 500);
})
}
You can use the anti-pattern for initializing the component using the props as follow:
constructor(props) {
super(props);
const {
name,
description
} = this.props;
this.state = {
inputs: {
name,
description
}
}
In the constructor or in the componentDidMount hook like bellow:
componentDidMount () {
const {
name,
description
} = this.props;
this.setState({
...this.state,
inputs: {
name,
description
}
});
}
The later allow us to restore the state from the store, at every component mounting.
Also if you need to change the form from a parent component, you can expose a function to that parent. By setting for setInputs() method that is binded. And in the construction, you execute the props (that is a getter method) getSetInputs(). (A useful case is when you want to reset the forms at some conditions or states).
constructor(props) {
super(props);
const {
getSetInputs
} = this.props;
// .....
if (typeof getSetInputs === 'function') getSetInputs(this.setInputs);
}
To understand better what i did above, here how i'm updating the inputs:
// inputs change handlers
onNameChange(evt) {
const { value } = evt.target;
this.onInputsChange(
{
name: value
},
evt
);
}
onDescriptionChange(evt) {
const { value } = evt.target;
this.onInputsChange(
{
description: value
},
evt
);
}
/**
* change = {
* name: value
* }
*/
onInputsChange(change, evt) {
const { onInputsChange, roomId } = this.props;
this.setState({
...this.state,
inputs: {
...this.state.inputs,
...change
}
}, () => {
clearTimeout(this.onInputsChangeTimeoutHandler);
this.onInputsChangeTimeoutHandler = setTimeout(() => {
if (typeof onInputsChange === "function")
onInputsChange(change, roomId, evt);
}, 500);
})
}
and here is my form:
const {
name='',
description=''
} = this.state.inputs;
// ....
<Form className="form">
<Row form>
<Col md={6}>
<FormGroup>
<Label>{t("Name")}</Label>
<Input
type="text"
value={name}
disabled={state === "view"}
onChange={this.onNameChange}
/>
{state !== "view" && (
<Fragment>
<FormFeedback
invalid={
errors.name
? "true"
: "false"
}
>
{errors.name !== true
? errors.name
: t(
"You need to enter a no existing name"
)}
</FormFeedback>
<FormText>
{t(
"Enter a unique name"
)}
</FormText>
</Fragment>
)}
</FormGroup>
</Col>
{/* <Col md={6}>
<div className="image">Image go here (one day)</div>
</Col> */}
</Row>
<FormGroup>
<Label>{t("Description")}</Label>
<Input
type="textarea"
value={description}
disabled={state === "view"}
onChange={this.onDescriptionChange}
/>
{state !== "view" && (
<FormFeedback
invalid={
errors.description
? "true"
: "false"
}
>
{errors.description}
</FormFeedback>
)}
</FormGroup>
</Form>

How to use the component string returned from server in React via AJAX

All:
I am pretty new to React, I am trying to render a component from the string return by Server side ReactDomServer.renderToString(), could anyone give me a working patrn or example to do this in AJAX?
A case will be:
One the init page, there is a dropdown, you choose different type of componnet, then it will submit AJAX request to server, then server return according string, then the page will render that component on it.
Thanks
From the comments on your question, it sounds like what you're looking to do is dynamically render a UI.
Your request was for an example of a drag-and-drop rendering workflow, but that would stray too far from your question. It's important that we first tease out the many components and then focus on the one that's interesting for this question. We have a data layer and server-side responsible for storing information, business logic for determining how components should render where and when, interaction paradigms like drag and drop that work within these rules, and the rendering of components based on them.
All of these are separate concerns that must be considered independently. For example, drag and drop is one way to add components, but it is likely to not be the only way, so why couple the two? That leaves us with just rendering dynamic components, which I shall consider here. I'll be using ES2015 syntax to make the code cleaner.
First, we have a main component that does the wrapping:
const Renderer = React.createClass({
render () {
// ...
},
});
ReactDOM.render(
<Renderer layout={layout} />,
document.getElementById( 'app' )
);
Now let's consider the components you mentioned, which will be pure:
const Button = ({ text }) => (
<button>{text}</button>
);
const Input = ({ type = "text", placeholder }) => (
<input type={type} placeholder={placeholder} />
);
And some container for available components (which would likely also have metadata and rules about each):
const Components = {
Button,
Input,
};
And now let's assume we have a configuration defined in json:
{
"name": "My Interface",
"layout": [
{ "id": 123, "component": "Input", "placeholder": "keywords..." },
{ "id": 456, "component": "Button", "value": "Search!" },
],
}
This is highly simplified, but you can imagine this document showing all properties for a deeply nested UI, perhaps sporting different types of containers like rows and columns. Now we can assume the JSON property layout is the layout property passed to the Renderer above. Now our render function can look like this (highly simplified):
render () {
const children = this.props.layout.map( ({ component, ...props }) => {
const Component = Components[ component ];
return <Component {...props} />
});
return (
<div className="component-view">
{children}
</div>
);
}
Whenever the model changes, we would re-render the component tree and see what we should. There is a lot that would have to go into something like this to get a full UI editor - that's a massive undertaking. But with proper design principles and separation of concerns, it's at least doable.
To return to drag and drop briefly, if we were to drag and drop, we would note its place and insert the component into the tree however made sense based on the component and the state of the item onto which it's dropped, etc. The result of the operation, assuming it was successful, would be a mutated layout tree, which triggers a re-render.
Note: I completely ignored performance considerations.

Categories

Resources