too much render with react markdown - javascript

I am using React Markdown (https://www.npmjs.com/package/react-markdown) to render markdown content in my NextJS project.
When I refresh I have two "toto" & "titi" in my terminal... It is normal or what's wrong with this code?
import Head from 'next/head';
import ReactMarkdown from 'react-markdown';
function Section ({ data }) {
const content = JSON.parse(data.markdown);
const {
title,
sortContent
} = data;
console.log('toto');
return (
<>
<main>
<h1>{title}</h1>
<h1>{sortContent}</h1>
<ReactMarkdown source={content.default} escapeHtml={false} />
</main>
</>
)
}
export async function getServerSideProps (context) {
const json = await import('../../content/article1/data.json');
const content = await import('../../content/fr/article1/content.md');
console.log('titi');
return {
props: {
data: {
title: json.title_content,
sortContent: json.short_content,
markdown: JSON.stringify(content)
}
}
}
}
export default Section

It's part of Reacts development tooling, StrictMode. It is expected and only applies in development mode. You can remove the StrictMode to see it only render the expected number of times, but obviously you lose some development tooling. This tooling can warn you about certain unsafe or unwise practices you might want to avoid such as using legacy APIs.
More details here:
Reactjs Docs
A blog with a good overview

If this is truly the only code you have, then it looks like it's normal. You may have other code that uses these components and that's why in shows twice. But based off the code you have right there, there's no bug.

This is a known side-effect of using React.StrictMode, only in debug mode. You can read more about this here.
Strict mode can’t automatically detect side effects for you, but it
can help you spot them by making them a little more deterministic.
This is done by intentionally double-invoking the following functions:
Class component constructor, render, and shouldComponentUpdate methods
Class component static getDerivedStateFromProps method
Function component bodies
State updater functions (the first argument to setState) Functions passed to useState, useMemo, or useReducer

Related

I have this React Invalid Hook Call Error that I'm getting and I wanted to see if I was breaking the rules of hooks or is it something else?

I'm getting the error below.
Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app
See (link I couldn't add) for tips about how to debug and fix this problem.
You might have mismatching versions of React and the renderer (such as React DOM)
Here is my code. Is it breaking rules of hooks or is the issue something else?
import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
import { useData } from 'useData';
export const checkReference = ({
refId,
}) => {
const data = useData(); //useContext hook
let refData = {};
if (refId) refData = data.getReference(refId);
useEffect(() => {
console.log('INITIAL LOGIC');
if (refData.parameter){
console.log('SECONDARY LOGIC', refData);
}
}, [])
checkReference.propTypes = {
refId: PropTypes.string,
}
checkReference.defaultProps = {
refId: null,
}
}
I am calling it from another file using
checkReference('page-name');
I've got the same issue in my Next.js app. It was a cache related issue. you can try these steps.
Delete node_modules and .next folders
Run npm install or yarn
Start your project again
React hooks are intended to be used inside Functional components like:
export const CustomComponent = () => {}
export function CustomComponent() {}
They cannot be used in normal function because it won't exist inside the context of a React component. If you want to use things like useState or useEffect inside functions defined outside a component, you have to create a custom hook. That is, create a function with the use prefix (e.g. useCheckReference) and then use it like:
export const MyComponent = () => {
const reference = useCheckReference()
}
In that way React knows that that function is presumably gonna be called inside a component and the use of hooks is reliable, also is going to make some optimizations related to hooks and components life cycle.

Next.js: How to dynamically import external client-side only React components into Server-Side-Rendering apps developed?

I know this question has been asked multiple times before but none of the solution seems to work.
I'm trying to use the library 'react-chat-popup' which only renders on client side in a SSR app.(built using next.js framework) The normal way to use this library is to call import {Chat} from 'react-chat-popup' and then render it directly as <Chat/>.
The solution I have found for SSR apps is to check if typedef of window !=== 'undefined' in the componentDidMount method before dynamically importing the library as importing the library normally alone would already cause the window is not defined error. So I found the link https://github.com/zeit/next.js/issues/2940 which suggested the following:
Chat = dynamic(import('react-chat-popup').then(m => {
const {Foo} = m;
Foo.__webpackChunkName = m.__webpackChunkName;
return Foo;
}));
However, my foo object becomes null when I do this. When I print out the m object in the callback, i get {"__webpackChunkName":"react_chat_popup_6445a148970fe64a2d707d15c41abb03"} How do I properly import the library and start using the <Chat/> element in this case?
Next js now has its own way of doing dynamic imports with no SSR.
import dynamic from 'next/dynamic'
const DynamicComponentWithNoSSR = dynamic(
() => import('../components/hello3'),
{ ssr: false }
)
Here is the link of their docs: next js
I've managed to resolve this by first declaring a variable at the top:
let Chat = ''
then doing the import this way in componentDidMount:
async componentDidMount(){
let result = await import('react-chat-popup')
Chat = result.Chat
this.setState({
appIsMounted: true
})
}
and finally render it like this:
<NoSSR>
{this.state.appIsMounted? <Chat/> : null}
</NoSSR>
You may not always want to include a module on server-side. For
example, when the module includes a library that only works in the
browser.
Import the library normally in child component and import that component dynamically on parent component.
https://nextjs.org/docs/advanced-features/dynamic-import#with-no-ssr
This approach worked for me.

Debugging why react-native release build crushes and debug one works fine

I was working in Debug mode where everything seemed fine, however when I build my app to TestFlight (i.e. release build) it crashed at LaunchScreen.
After some time and debugging I narrowed issue down to following code
import React from 'react'
import { Subscribe } from 'unstated'
const getStoreAsProps = (storeArr) => {
const storeProps = {}
storeArr.map(value => (storeProps[value.constructor.name] = value))
return storeProps
}
const withStore = (...args) => (Element) => () => (
<Subscribe to={[...args]}>{(...args) => <Element {...getStoreAsProps(args)} />}</Subscribe>
)
export default withStore
The way this works is as follows
import React from "react"
import { Text } from "react-native"
import AuthStore from "./store/Auth"
import RouterStore from "./store/Router"
import withStore from "./store"
class MyComponent extends React.Component {
render() {
const {AuthStore, RouterStore} = this.props
return <Text>{AuthStore.state.username} {RouterStore.state.pathname}</Text>
}
}
export default withStore(AuthStore, RouterStore)(MyComponent)
So essentially withStore is a higher order component that can take in any number of arguments, in this case Stores and pass them to Subscribe component (this is part of state management library I am using called unstaded) which in turn returns render props that are then passed to my component as props.
It works fine in Debug mode, but I get error like this in Release mode
undefined is not an object while evaluating e.state
This error from XCode debug logs.
I think something somewhere during Release build is different compared to Debug one that makes this.props.AuthState for example [undefined] and error is thrown when I am specifying <Text>{AuthStore.state.username} {RouterStore.state.pathname}</Text> where my Store props are undefined, hence I can't access their state.
I'd love to keep this Higher Order Component I made for store, as it enables really nice dev experience, but need to be able to debug what exactly breaks in release build, which thus far I was not able to do.
What optimisations are made during release build that could have effect here?
Answer originates from: https://github.com/facebook/metro/issues/182#issuecomment-398052619
Issue was in accessing value.constructor.name where I was assuming it will always be the same as my Container name. During minification these change, hence it was undefined, adding unique identifier to a class resolves the issue

Can't get the most basic mobx store to work with observer

I just started out trying mobx-react using stores, and want to use a store plus a single observable, but can't even get this to work.
With #observer, I get the error Uncaught TypeError: Cannot assign to read only property 'render' of object '#<ProxyComponent>'.
Without it, the value becomes 1.
I'm not sure what's going wrong here, any ideas?
import {observable} from 'mobx'
import {inject, observer} from 'mobx-react'
class AppStore {
#observable value = 1;
}
#inject('store') #observer
class App extends React.Component {
render(){
const {store} = this.props
return (
<div>
{store.value}
</div>
)
}
}
const render = (Component) => {
const appStore = new AppStore()
ReactDOM.render(
<AppContainer>
<Provider store={appStore}>
<Component/>
</Provider>
</AppContainer>,
document.getElementById('root'),
)
}
render(App)
Your code is bit unclear, like from where are you importing Provider and ReactDOM.And also since render is a function used by ReactDOM so the render() function you have defined might conflict with the built in render() function.
And also here it is explained
In general there are three ways in which you can pass stores in MobX
1) Explicitly via props. Easy to test and clear to follow, but can become
clumpsy when you have deeply nested structures or many stores (you can
solve the latter by having a store for stores)
2) Import stores in the
components directly and just use them :) It's the MVP of passing
stores around, but stand alone testing of components becomes tricky
quickly as you have to make sure your global stores are in the right
state first
3) Pass stores around via React's context mechanism. Redux's
Provider uses that, as does the mobx-connect package. Context is
passed implicitly and deep component can extract data out of the
context, but it is still easy to test as you only have to make sure
you set up some context before testing the component.
In your case you are using the 3rd point.So I have created a jsfiddle here,
where the store is passed as props as in point 1.
Turns out this was a configuration (webpack hot loader) issue, and not an issue of the code itself (which runs under a jsfiddle).
Adding 'react-hot-loader/babel' to 'plugins' in webpack's 'babel-loader' appears to work.

Meteor React Subscription

What is alternative way of using package 'react-meteor-data' ? I'm using ES6 for writing react component. What would be best approach for writing meteor subscription in react component so that it will re-render the component if anything change on the server side.
What would be best approach for writing meteor subscription in react
component so that it will re-render the component if anything change
on the server side.
The best approach is using react-meteor-data. What is wrong with this package, that makes you think to not use it?
It even allows you to separate / decouple React Components from Meteor. This is really great because when you reach the point of having written some components that you want to reuse in another non-Meteor project you are free to go without greater hassle.
Of course you could write your own subscription container for react, but with this package you have all important stuff you need plus it is maintained and tested.
If you have trouble setting up a container for subscriptions, you may dig deeper into these tutorials:
https://guide.meteor.com/react.html
https://themeteorchef.com/tutorials/using-create-container
Using react-meteor-data, you first create a HOC container that subscribes to the data and passes it down as props to your component.
Container:
import { createContainer } from 'meteor/react-meteor-data';
export default FooContainer = createContainer(() => {
// Do all your reactive data access in this method.
// Note that this subscription will get cleaned up when your component is unmounted
var handle = Meteor.subscribe("todoList", this.props.id);
return {
currentUser: Meteor.user(),
listLoading: ! handle.ready(),
tasks: Tasks.find({listId: this.props.id}).fetch(),
};
}, Foo);
Component:
import FooContainer from './FooContainer';
class App extends React.Component {
render() {
return (
<div>
{this.props.currentUser.name}
</div>
)
}
}
export default FooContainer(App);
Check out React docs for Higher Order Components to understand how the container works.

Categories