unable to render HTML inside react native - reactjs

I want to run this component inside react native
<StyledFirebaseAuth uiConfig={uiConfig} firebaseAuth={firebase.auth()} />
currently, I am using react-native-render-html package
and doing likewise
import React from "react";
import { View, Text } from "react-native";
import HTML from "react-native-render-html";
import StyledFirebaseAuth from "react-firebaseui/StyledFirebaseAuth";
const PhoneAuth = () => {
const uiConfig = {
signInFlow: "popup",
signInOptions: [
{
provider: firebase.auth.PhoneAuthProvider.PROVIDER_ID,
recaptchaParameters: {
type: "image",
size: "invisible",
badge: "bottomleft",
},
defaultCountry: "+91",
whitelistedCountries: ["IN", "+91"],
},
],
// callbacks: {
// signInSuccessWithAuthResult: function (authResult) {
// var user = authResult.user;
// const data = { phone: user.phoneNumber };
// props.setPhoneNumber(data);
// },
// },
};
const htmlContent =
`<StyledFirebaseAuth uiConfig={uiConfig} firebaseAuth={firebase.auth()} />`
return (
<View>
<HTML html={htmlContent} />
</View>
);
};
export default PhoneAuth;
but as HTML content is a string it's not picking the variables
and I get a blank screen.

If you're creating a custom HTML tag or element you have to tell the renderers to do so, i.e.:
const content = `<bluecircle></bluecircle>`;
...
renderers: {
bluecircle: () => <View style={{ width: 20, height: 20, borderRadius: 10, backgroundColor: 'blue' }} />
}
You might try the following
import HTML from 'react-native-render-html'
...
render() {
// The html you want to render
const html = `
<div>
</div>
`
const styles = {}
const renderers = {
StyledFirebaseAuth: (htmlAttribs, children, passProps) => {
return (
<StyledFirebaseAuth
{...passProps} />)
}
}
return (
<HTML
// Required. The html snippet you want to render as a string
html={html}
// The styles to supply for each html tag. Default styles
// are already pre-provided in HTMLStyles.js. The additional
// styles that you provide will be merged over these, so if
// you need some funky red background on your h1, just set
// the background
htmlStyles={styles}
// Renderers to use for rendering specific HTML elements.
// Default renderers are pre-provided in HTMLRenderers.js.
renderers={renderers}
)
}
See docs

set style to view flex: 1 as showed in example
<ScrollView style={{ flex: 1 }}>
<HTML
html={htmlContent}
imagesMaxWidth={Dimensions.get("window").width}
/>
</ScrollView>

You can use WebView for this purpose. No need to use any other library.
<WebView
originWhitelist={['*']}
source={{ html: htmlContent }}
/>
See API reference for more details.

Related

Dark theme does not work with React Stitches

I'm using Stitches in React to handle my CSS and theming. I have the following code:
import React from 'react'
import { createStitches, globalCss } from '#stitches/react'
const { theme, createTheme } = createStitches({
theme: {
colors: {
text: 'blue',
bodyBg: 'lightgray',
},
},
})
const darkTheme = createTheme('dark-theme', {
colors: {
bodyBg: 'black',
},
})
const globalStyles = globalCss({
'body': {
color: '$text',
backgroundColor: '$bodyBg'
},
});
function App() {
globalStyles()
return (
<div className='App'>
<h1>Hello World!</h1>
</div>
)
}
export default App
As you can see, I have a default theme, and then a dark theme that extends the default theme while overriding some properties (in this case, the bodyBg). I'm applying these styles directly in my <body>. The default theme works fine, but the dark theme does not. When I add the .dark-theme class to my <html>, nothing changes (the background should turn black). What exactly am I doing wrong here?
You are probably trying to add the class directly to the body in the developer tools which doesn't work.
I managed to make it work with a button onClick event:
const darkTheme = createTheme('dark-theme', {
colors: {
bodyBg: 'black',
},
})
function App() {
const setBlackTheme = () => {
document.body.classList.remove(...document.body.classList);
// Here we set the darkTheme as a class to the body tag
document.body.classList.add(darkTheme);
}
globalStyles()
return (
<div className='App'>
<button onClick={setBlackTheme}>Dark Theme</button>
<h1>Hello World!</h1>
</div>
)
}
export default App
Try it and let's see if it works for you as well.

code block not displaying when previewing in react-quill

In this code, I am trying to insert a code block using react-quilljs
import React, { useState } from 'react';
import hljs from 'highlight.js';
import { useQuill } from 'react-quilljs';
import 'quill/dist/quill.snow.css'; // Add css for snow theme
export default () => {
hljs.configure({
languages: ['javascript', 'ruby', 'python', 'rust'],
});
const theme = 'snow';
const modules = {
toolbar: [['code-block']],
syntax: {
highlight: (text) => hljs.highlightAuto(text).value,
},
};
const placeholder = 'Compose an epic...';
const formats = ['code-block'];
const { quill, quillRef } = useQuill({
theme,
modules,
formats,
placeholder,
});
const [content, setContent] = useState('');
React.useEffect(() => {
if (quill) {
quill.on('text-change', () => {
setContent(quill.root.innerHTML);
});
}
}, [quill]);
const submitHandler = (e) => {};
return (
<div style={{ width: 500, height: 300 }}>
<div ref={quillRef} />
<form onSubmit={submitHandler}>
<button type='submit'>Submit</button>
</form>
{quill && (
<div
className='ql-editor'
dangerouslySetInnerHTML={{ __html: content }}
/>
)}
</div>
);
};
Using the above code, I get the following preview of the editor's content
There are two problems with this:
There is no code syntax highlighting, as I want to achieve this using the highlihgt.js package, inside the code block inside the editor, and
The code block is not displayed (with the black background and highlighting syntax when it's working) in the previewing div outside the editor.
How can I fix these two issues?
Your code is getting marked up by highlight.js with CSS classes:
<span class="hljs-keyword">const</span>
You are not seeing the impact of those CSS classes because you don't have a stylesheet loaded to handle them. You need to choose the theme that you want from the available styles and import the corresponding stylesheet.
import 'highlight.js/styles/darcula.css';
Look at the css in the editor mode. It depends on two class names ql-snow and ql-editor.
You can fix this issue by wrapping it around one more div with className ql-snow.
<div className='ql-snow'>
<div className='ql-editor' dangerouslySetInnerHTML={{ __html: content }}>
<div/>
</div>
This should work.
I got the same issue and when I used hjls what happened was that I got syntax highlighting in the editor but not in the value.
If you noticed the syntax gets highlighted some seconds after you write the code block, this means that the value gets set before the syntax gets highlighted.
So, I just set the value after 2 seconds using setTimeout and this solved my problem
Like this:
<ReactQuill
theme="snow"
value={value}
onChange={(content) => {
setTimeout(() => {
setValue(content)
}, 2000)
}}
modules={modules}
formats={formats}
bounds="#editor"
placeholder="Write something..."
className="text-black dark:text-white"
/>
I recently implemented this logic into my project. I used React Quill for the text editor, implemented syntax highlighting to it using highlight.js, and I also used React Markdown to display the formatted content on my website. React Markdown by default works with markdown, so you need a plugin (rehype-raw) to get it to parse HTML. This is my code, from my project. Just remove some of the unnecessary stuff from here that is specific to my project and use what you need.
// PLUGINS IMPORTS //
import { Typography } from "#mui/material";
import { useEffect, useState } from "react";
import hljs from "highlight.js";
import "react-quill/dist/quill.core.css";
import "react-quill/dist/quill.snow.css";
import "highlight.js/styles/atom-one-dark.css";
import ReactQuill from "react-quill";
import ReactMarkdown from "react-markdown";
import rehypeRaw from "rehype-raw";
// COMPONENTS IMPORTS //
import { CreateButton } from "components/atoms";
// EXTRA IMPORTS //
import styles from "./create-post.module.css";
import { ETheme } from "types/theme";
/////////////////////////////////////////////////////////////////////////////
type CreatePostProps = {};
hljs.configure({
// optionally configure hljs
languages: ["javascript", "python", "c", "c++", "java", "HTML", "css", "matlab"],
});
const toolbarOptions = [
["bold", "italic", "underline", "strike"],
["blockquote", "code-block"],
[{ list: "ordered" }, { list: "bullet" }],
["link"],
[{ indent: "-1" }, { indent: "+1" }],
[{ header: [1, 2, 3, 4, 5, 6, false] }],
[{ align: [] }],
];
const modules = {
syntax: {
highlight: function (text: string) {
return hljs.highlightAuto(text).value;
},
},
toolbar: toolbarOptions,
clipboard: {
// toggle to add extra line breaks when pasting HTML:
matchVisual: false,
},
};
const formats = [
"header",
"font",
"size",
"bold",
"italic",
"underline",
"strike",
"blockquote",
"code-block",
"list",
"bullet",
"indent",
"link",
"align",
];
const placeholder = "Description";
const CreatePost = (props: CreatePostProps) => {
const [markdownText, setMarkdownText] = useState("");
useEffect(() => {
console.log({ markdownText });
}, [markdownText]);
return (
<main className={`${styles["create-post-wrapper"]}`}>
<header className={`${styles["create-post-header"]}`}>
<Typography variant="h6">Create a post</Typography>
</header>
{/* making the border a seperate div makes it easier to apply margin */}
<div className={`${styles["border"]} ${styles["top"]}`}></div>
<div>Choose a community</div>
<article className={`${styles["create-post"]}`}>
<section className={`${styles["inner-create-post"]}`}>
<section>Title</section>
<ReactQuill
value={markdownText}
onChange={value => setMarkdownText(value)}
theme="snow"
modules={modules}
formats={formats}
placeholder={placeholder}
/>
<div className="ql-snow">
<div className="ql-editor">
<ReactMarkdown children={markdownText} rehypePlugins={[rehypeRaw]} />
</div>
</div>
<div className={`${styles["border"]} ${styles["bottom"]}`}></div>
<section className={`${styles["post-button"]}`}>
<CreateButton
theme={ETheme.LIGHT}
buttonText="Post"
buttonProps={{
fullWidth: false,
}}
/>
</section>
</section>
</article>
</main>
);
};
export default CreatePost;
You can always add more options to toolbarOptions, but don't forget to also add them to formats if you do. Also, if you want to keep formatting anywhere else in your website, you need the two divs with these 2 classes around your markdown.
React Quill bacially saves everything into a string with HTML and classes, you import styles for those classes and it works like magic.

webview element is not loading in reactjs application?

I have created a function that returns WebView
const WebviewComponent = () => (
<webview id="test" src="https://www.google.com" style={{ height: "700px", width:"800px", autoSize:"on", minWidth:"576", minHeight:"432" }} />
)
and I called this function in app.js. When I try to launch the application the src url is not loading.
WebView source type is not a string. You should check WebView documentation or see the usage below to understand how it works.
Usage
import React, { Component } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { WebView } from 'react-native-webview';
class MyWebComponent extends Component {
render() {
return <WebView source={{ uri: 'https://reactnative.dev/' }} />;
}
}
In your case, It will be
const WebviewComponent = () => (
<WebView
style={{ flex: 1 }}
source={{ uri: 'https://www.google.com' }} />
)

how to change component background color changing state in react.js?

I am working on a task where I need to change component background by clicking on a button and changing state. I am not supposed to use React Hooks. So far I've got:
import React from 'react'
import ReactDOM from 'react-dom'
class Main extends React.Component {
constructor(props) {
super(props)
}
render() {
const {
colorChange,
styles
} = this.props
const text = this.props.data
return (
<main style={styles} >
<h1>welcome</h1>
<button
onClick={colorChange}
>
Change color
</button>
</main>
)
}
}
class App extends React.Component {
state = {
styles: { backgroundColor: 'white' },
}
colorChange = () => {
let backgroundColor = 'white'
let changedColor = 'black'
let backGround = this.state.styles==='white' ? changedColor : backgroundColor
this.setState({backGround})}
render() {
return (
<Main
colorChange={this.colorChange}
/>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
but that doesn't do anything. Where am I making a mistake?
First pass styles as a prop to main <Main colorChange={this.colorChange} style={this.state.styles} /> its currently undefined.
second, this.state.styles is as object and you're comparing like
this.state.styles === "white"
and you should acess backgroundColor in the object:
this.state.styles.backgroundColor === "white"
and last when you do setState({backGround}) you're creating a item with key backGround (which isn't a valid css property) and isn't inside styles tag as well. Your state end up being like this:
this.state = {
backGround: 'black',
styles: {
backgroundColor: 'white'
}
}
so do like this:
this.setState({
styles: {
backgroundColor: backColor
}
})
also i recomend calling colorChange like this to avoid infinite re-renders:
<button onClick={() => colorChange()}>Your Button</button>
My suggestion would be that you simply use the onColorChange() function to add/remove a class.
If you MUST pass the styles as a parameter, you could also save only the value of the color ('white', 'black') on the state and when you pass it on to the component use the value only

React Navigation Header not hiding/showing

I'm using react navigation. I want to hide the header onPress and show on another function. I am able to hide it but not show it again.It seems that I can do only 1 function on the header. My code is:
import React, { Component } from 'react'
import {
View, Text, Button, Alert,
} from 'react-native'
import MaterialIcons from "react-native-vector-icons/MaterialIcons";
class HeaderTest extends Component {
static navigationOptions = ({navigation}) => ({
header: navigation.state.params ? navigation.state.params.showHeader : null,
title: 'HeaderTest'
});
constructor (props) {
super(props);
this.state = { showHeader: true}
this._handleHide = this._handleHide.bind(this);
this._handleShow = this._handleShow.bind(this);
}
_handleHide(){
this.props.navigation.setParams({
header: null
})
}
_handleShow(){
this.props.navigation.setParams({
header: true
})
}
render(){
return(
<View style={thisStyles.container}>
<Button onPress={this._handleHide} title="Hide Header" />
<Button onPress={this._handleShow} title="Show Header" />
</View>
)
}
}
export default HeaderTest;
I want to be able to hide and show the header on the button onPress. What am I doing wrong?
Please help.
Update 1:
_handleHide(){
this.props.navigation.setParams({
header: false
})
}
_handleShow(){
this.props.navigation.setParams({
header : (HeaderProps) => <View style={{ height:20,backgroundColor:'blue' }} ></View>
})
}
componentWillMount(){
this.props.navigation.setParams({
header : (HeaderProps) => <View style={{ height:20,backgroundColor:'blue' }} ></View>
})
}
According to the docs in React-Navigation,
header
React Element or a function that given HeaderProps returns a React
Element, to display as a header. Setting to null hides header.
Hence to hide the header just use
header = null;
Now to show header u must provide a custom element or a function which returns a element not 'true'
header = <View style={{ height:20,backgroundColor:'blue' }} ></View>
or
header = (HeaderProps) => <View style={{ height:20,backgroundColor:'blue' }} ></View>
If u want to just hide and show the default Header instead of creating a custom one,
source: https://github.com/react-community/react-navigation/issues/1444
//Import Header from 'react-navigation' and render it back with the headerProps u get
import { Header } from 'react-navigation';
static navigationOptions = () => ({
header: (headerProps) => <Header {... headerProps} />,
});

Resources