React, nested component with external component - reactjs

I'm creating a documentation in React for an internal project. To help users to enter the good informations, I ask them some informations in beginning of the documentation such as their username or their machine's IP and save them in a cookie (we have no backend). These datas are display in the documentation to help them to configure their environment.
We also include some codes, command lines and configuration in yaml. To make the code more clear, I use React Syntax Highlighter. It works well except for on things and I don't find a work around: Sometime, the code include the Username or IP. But when I include the components to display these datas in the code, it's not display correctly.
Example:
const config_data = '# Maintainer\n\
MAINTAINER "' + <DisplayName /> + '"\n\n\
# copy your file\n\
COPY ./test.test /usr/local/test.test';
class Test extends React.Component {
render() {
return(
<div>
<SyntaxHighlighter language="dockerfile">
{config_data}
</SyntaxHighlighter>
</div>);
}
}
The result will give me:
# Maintainer
MAINTAINER "[object Object]"
# copy your file
COPY ./test.test /usr/local/test.test
I find this issue which helped me to understand what happens but because the React Syntax Highlighter component is not mine, I can not (not in my knowledge at least) modify it. I also tried to get the data directly from the cookies to display the data directly but the result is the same.
I don't know if it's a bug of the component, if I can render my own component before to include it or if I missed something.

You can use ReactDOMServer to convert the component into a string/markup.
import * as ReactDOMServer from 'react-dom/server';
const config_data = `# Maintainer\n\
MAINTAINER ${ReactDOMServer.renderToStaticMarkup(<DisplayName />)} \n\n\
# copy your file\n\
COPY ./test.test /usr/local/test.test`;

Related

Creating preformatted text and code in React app

I am making a blog website in React in which user can submit code with other text. The entire code and other text will later be saved into the database. I am looking for the functionality like Stackoverflow's in which user can submit code and it is shown in the post in the original format.
I tried my best to search for the exact name of this functionality(My best guess is using LateX) but couldn't find any. So my exact question is what module or package do I need to represent the code submitted by the user in the original format as in Stackoverflow's question.
Please help me in the problem so I can get along with my work on my website.
After a bit of research into the topic of markdown, I found that react-markdown is a npm module that can be used to create markdown in text string. It is almost similar to the one used in Stackoverflow. But the recent version seems to have some bug, so I used an older version(5.0.0). If you also want to include syntax highlighting, you can use highlight.js. It can be very easily included with react-markdown. Below is an example of react-markdown:
import React from "react";
import ReactMarkdown from "react-markdown";
export default class App3 extends React.Component {
render(){
var value='
#Heading1
<b>line break</b>
_italics_';
return (
<div className="App">
<ReactMarkdown source={value} />
</div>
);}
}
u can also use
dangerouslySetInnerHTML
if u don't to install 3rd libary

Import a file as a string (or source asset) in Gatsby / React

I want to import .ts, .tsx, .js, and .jsx files into a react component and render them within a PrismJS highlighting block. For example, let's say I have a TypeScript file with functionA in it that I want to highlight in my actual website:
functionA.ts:
export function functionA() {
console.log("I am function A!");
}
I want to include this in a different component. The problem is, when I import it, I am obviously importing the webpack module version of it. My weak attempt at trying to get my function render in a react component looks like this:
MyComponent.tsx:
import * as React from "react"
import { functionA } from "./functionA"
export function MyComponent() {
return (
<>
<h1>Here is your code block:</h1>
<pre>
<code>
{functionA.toString()}
</code>
</pre>
</>
)
}
and what will actually render on the page where the code block is will look something like this:
Here is your code block:
WEBPACK__IMPORT.functionA() {
console.log("I am function A!")
}
I can't exactly remember what the .toString() function output looked like, but the point is it is NOT just the contents of the file how it appears in a code edit for example - it has been modulized by WebPack.
So, in a Gatsby project, how can i get these various code snippets to be imported directly as a string, purely as they are written, without WebPack enacting its import stuff on it? Is there a plugin or some way to tell Webpack to use the imported file as its asset/source module type? I know for MD or MDX files there is the gatsby-remark-embed-snippet, but I am building a component based HTML page and can't use MD or MDX files!
It's very late, and perhaps I just can't see the forest from the trees, I know there must be a way to do this...
You need to require the file using webpack's raw-loader, i.e:
const functionA = require("!!raw-loader!./functionA");
This works for create-react-app, as in the solution discussed here, and this works for Gatsby as well!
After using require on such a file, the file contents can be rendered in the component as:
<pre>{functionA.default.toString()}</pre>
It's then up to you to add syntax highlighting using a tool like prism or similar.
Note this solution will only work as long as Gatsby V3 continues to use WebPack v4, as raw-loader is deprecated in WebPack v5 and will be phased out for asset/source type modules.

How to resolve react-video-js-player failing to load media

Hello I am trying to use the react video js player but I am getting the error below:
The media could not be loaded, either because the server or network failed or because the format is not supported.
At first, I thought maybe it was the video type because Initially it was a .mkvi video I then changed to mp4 and still nothing I get the same error can I please get help
Code Below: VideoList.js
import React from 'react';
import VideoPlayer from 'react-video-js-player';
const VideoList = (props) =>{
let videos = props.listVideos
return(
<div>
{videos.map(video =>{
return(
<div key={video.id}>
<h3>{video.lecturer}</h3>
<VideoPlayer src={video.video} width="720" height="420" playbackRates={[0.5, 1, 3.85, 16]}/>
</div>
)
})}
</div>
)
}
export default VideoList
Like I said on my comments, typically this error will occur if the video is not existing, has issues with the encoding, file extension, etc. See this example I've written.
In the end, I was correct and the video.video object was returning a relative path instead of an absolute path which resulted in an incorrect link.
Regarding the OP's current solution for this issue, this is not an ideal architecture because it will probably fail when you deploy to production, switch domains, or even just switch ports. Concantenating your base url is fine (e.g., http://127.0.0.1:8000/) but I would have this variable as a single source of truth probably residing at a state at the topmost component or as an environment variable so that anytime you change domains, ports, or IP you can simply change this variable and you won't have to go through all of your components 1 by 1.
Example implementation on Class based components:
Parent component:
state = {
base_url: `http://127.0.0.1:8000/api/`, // local dev api
// base_url: `https://production-server:80/api/` // live site api
// or an environment variable as described on my answer
}
Child component:
<VideoPlayer src={`${this.props.base_url}${content.video}`}
So I managed to find the problem behind this, so I was getting data from the API but when I tried to access the video the API was not giving the full URL that is:
http://127.0.0.1:8000/media/lectures/<here_the_name_of_the_lecture_video>
But the API was giving me a relative path media/lectures/<here_the_name_of_the_lecture_video>
So I had to give the remaining the URL that which the API does not give when I render in the video i.e I had to write the following
<VideoPlayer src={`http://127.0.0.1:8000/api${content.video}`}
So I am wondering
Currently, this solution works but is this solution technically good? Because I am to believe that the API should be giving everything that I need I just have to make requests.
Can you please assist me to come up with a more technically viable solution for this problem

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 import a component or file in React using variables?

I'm building a web app using React that shows the blueprint for the building you select, in an already selected campus.
I have a "Content" component that loads the campus or building map, depending what you chose.
The "BuildingMap" component needs to load a specific blueprint according to what building you selected. It gets the props.building with the name of the building but I don't know how to load a component using that variable.
I have tried import, fetch and require but nothing seems to work.
Please help.
My code looks something like this:
//Content Component
<BuildingMap building={selectedBuilding} campus={selectedCampus} />
//BuildingMap Component
import *MyBlueprint* from (specific folder depending on the campus selected)
class BuildingMap extends React.Component {
render(){
return (
<div className="blueprint" id={this.props.building}>
{*MyBlueprint*}
</div>
)
}
}
Unfortunately, you cannot import/require components dynamically in React environment.
Depending on how many buildings/blueprints there are, it's possible to import them one by one, create component-building map and pick component by building ID.
If there are many/infinite components to load, I would surely pick another method - don't know content of your problem.
import BlueprintA from './BlueprintA'
import BlueprintB from './BlueprintB'
import BlueprintC from './BlueprintC'
// ...
class BuildingMap extends React.Component {
render(){
const C = {
buildingA: BlueprintA,
buildingB: BlueprintB,
buildingC: BlueprintC,
// ...
}[this.props.building]
return (
<div className="blueprint" id={this.props.building}>
<C />
</div>
)
}
}
This question is pretty old but as I was looking for how to solve the same problem let me give my answer. It can be done with dynamic import React.lazy:
const OtherComponent = React.lazy(() => import('./OtherComponent'));
See more details here: https://reactjs.org/docs/code-splitting.html#reactlazy
To add to #Andreyco's answer:
Using a lookup table of string IDs/names to component classes is a typical React idiom. One common use case is a modal manager component that can render multiple different types of modals. For some examples, see Dan Abramov's answer at "How can I render a modal dialog in Redux?" (not Redux-specific), as well as some of the related articles in the React Component Patterns#Modal Dialogs and Redux Techniques#UI sections of my React/Redux links list.
Per #azium's comment: it is definitely possible to use dynamic importing (via require.ensure() or the new import() function) to load chunks at runtime, and you could add the exports from those dynamically imported chunks into a lookup table when they are loaded.

Resources