Bonjour!
I want to create an mobile App which renders content written in markdown, similar to Obsidian. So far I successfully used the library react-native-markdown-display
to render markdown pages with non-interactive content, e.g. text, images and son on. Now I want to add interactive markdown content with custom rules, e.g. a map view, which needs hooks to work properly. Because the pages can change by user input and each page has different (interactive) content, I run in the problem of “Rendered more hooks than during the previous render”.
What would be the best strategy to tackle this problem?
While playing around I found out that if I create two react components Markdown
and Markdown1
, which basically are the same components just with a different name. I can give each component different markdown content and conditionally render one or the other, without error. Would this be a good way to solve this problem? If yes how does react differentiate react components? How could I dynamically create Markdown
components for different interactive content, which react could differentiate?
Would creating a screen in react-navigation
dynamically for every markdown page be a good solution?
2
Answers
I also dragged into same problem, but I resolved by split components
When the error happen code like this:
Error not coming after spliting components like this
Conditional/dynamic rendering
You can not call hooks conditionally. Calling hooks in loops, although I think it could be legal, is also at least shady and should be avoided. React Hooks must be called in the exact same order in every component render. Call them at the top level of a component (i.e. don’t nest it inside of anything more than the component ifself).
More on topic of "Rendered more hooks than during the previous render" error
I did ask if it’s the
useState
hook which causes the error because I suppose you did something like below:Changing state of components
I don’t know anything about
react-native-markdown-display
, but I checked out their documentation and it seems that if you want to change what content the Markdown component displays you just provide a different data to it. Let’s say you’ve got two constants holding markdown and two buttons which let you change which one is used:Instead of constants these could be files, data fetched from a server, user input – sky is the limit. What matters is what
setMarkdown
is called with, which in turn determines what sits in the state and then is passed to theMarkdown
component.Rendering lists
If you need to display a different set of elements based on some arbitrary data there is a number of ways you can achieve it.
You hold data in the state, like this:
then you map the data to elements, e.g. like this:
I don’t know where your markdown comes from so I will just provide a general way of adding some to the list:
If you hold an object or an array in the state, se sure to create a new one each time you want to update it since React compares references to tell if a change was made and does not examine contents of them.
A classic example is a Todo List. I encourage you to check out some examples. Here is a full example of Todo list on codesandbox.
Component tree
It creates a virtual DOM tree. Elements of this tree correspond to elements displayed on the screen.
Also, JSX is transpiled to
React.createElement
calls:You can see that
'h1'
was passed tocreateElement
so this is another piece by which React differenciates components – by the function (or tag) which is used to create the DOM tree.In the example above I used a map to create an arbitrary set of elements. There is a caveat to that.
(React docs on rendering lists)
The
key
is also used to differenciate elements. React holds data for each element and thekey
is necessary to assign state to the element which owns it. I usedindex
askey
which is fine as long as you don’t perform any manipulation on the list other than adding to the end. If, for example, you would remove an element from the beginning of the list and the indices would shift, the states would not shift with them and second element would get state from the first, third from second and so on. Thekey
needs to be unique. IDs and hashes are good askey
s because they are usually unique.Disclaimer
You didn’t provide and code so I had to guess some things and I’m not certain if anyhing from what I wrote above is going to be any helpful. Feel free to ask furher questions.