How to render HTML from a prop coming from MongoDB - node.js

I can't make my prop render in HTML. I'm making an app for a Christian ministry and I want to be able to post like a blog, I got quill working but I can't show the results rendered, is showing pure HTML.
I'v been trying to follow the rules of react-render-html, but my experience is little, so I don't really know what I'm missing. I try use 'renderHTML' but it doesn't work.
Below is my code, and if you see the screenshot, you will see that the first card is showing the HTML tags.
import React from 'react';
import { Container, Card, Button, CardTitle, CardText, CardColumns, CardSubtitle, CardBody, Collapse } from 'reactstrap';
import { CSSTransition, TransitionGroup } from 'react-transition-group';
import { connect } from 'react-redux';
import { getPosts, deletePost } from '../actions/postActions';
import PropTypes from 'prop-types';
import axios from 'axios';
import renderHTML from 'react-render-html';
import PostsForm from './extentions/PostsForm';
class Home extends React.Component {
componentDidMount() {
this.props.getPosts();
}
onDeleteClick = (id) => {
this.props.deletePost(id);
}
constructor(props) {
super(props);
this.onEntering = this.onEntering.bind(this);
this.onEntered = this.onEntered.bind(this);
this.onExiting = this.onExiting.bind(this);
this.onExited = this.onExited.bind(this);
this.toggle = this.toggle.bind(this);
this.state = {
collapse: false,
status: 'Closed',
ButtonText: "Submit Post"
};
}
onEntering() {
this.setState({ status: 'Opening...' });
}
onEntered() {
this.setState({ status: 'Opened' });
}
onExiting() {
this.setState({ status: 'Closing...' });
}
onExited() {
this.setState({ status: 'Closed', ButtonText: "Submit Post" });
}
toggle() {
this.setState(state => ({ collapse: !state.collapse, ButtonText: "Close" }));
}
formOpening = () => {
this.setState({
on: !this.state.on
})
}
render(){
const { posts } = this.props.post;
return(
<Container>
<div style={{float: "left"}}><h5>Current state: {this.state.status}</h5></div>
<div style={{float: "right"}}><Button
color="dark"
style={{marginButtom: '2rem'}}
onClick={this.toggle}>{this.state.ButtonText}</Button></div>
<Collapse
isOpen={this.state.collapse}
onEntering={this.onEntering}
onEntered={this.onEntered}
onExiting={this.onExiting}
onExited={this.onExited}
style={{clear: "both"}}
>
<Card>
<CardBody>
<PostsForm />
</CardBody>
</Card>
</Collapse>
<CardColumns style={{clear: "both"}}>
<TransitionGroup className="Posts">
{posts.map(({ _id, title, subtitle, postbody}) => (
<CSSTransition key={_id} timeout={500} classNames="fade">
<Card>
<CardBody>
<Button className="remove-btn" color="danger" size="sm" onClick={this.onDeleteClick.bind(this, _id)}>×</Button>
<CardTitle><h3>{title}</h3></CardTitle>
<CardSubtitle><h4>{subtitle}</h4></CardSubtitle>
<CardText>{postbody}</CardText>
<Button>Read More</Button>
</CardBody>
</Card>
</CSSTransition>
))}
</TransitionGroup>
</CardColumns>
</Container>
)
}
};
Home.propTypes = {
getPosts: PropTypes.func.isRequired,
post: PropTypes.object.isRequired
}
const mapStateToProps = (state) => ({
post: state.post
});
export default connect(mapStateToProps, { getPosts, deletePost })(Home);
Screenshot of how it looks now
I would like to see that the cards are acting like
Body Text ect etc etc not <p>Body Text ect etc etc</p>

You need to use dangerouslySetInnerHTML API.
From React Docs, slightly modified:
function createMarkup(html) {
return {__html: html};
}
function MyComponent({html}) {
return <div dangerouslySetInnerHTML={createMarkup(html)} />;
}
https://reactjs.org/docs/dom-elements.html

Related

React Native Context API returns undefined for state

All I am trying to do is to welcome the user on the screen. Here is the code.
context.js
import React, {Component} from "react";
const MyContext = React.createContext();
class MyProvider extends Component {
this.state = {
isAuthenticated: false,
user: {
name: "YYY",
email: "yyy#gmail.com"
}
};
render() {
console.log(this.state)
return (
<MyContext.Provider value = {this.state}>
{this.props.children}
</MyContext.Provider>
);
};
};
export {MyContext, MyProvider};
App.js Code
import React from 'react';
import {StyleSheet, Text } from 'react-native';
import {MyContext, MyProvider} from './src/context/context';
function App() {
return (
<MyProvider>
<Header />
</MyProvider>
)
}
export default class Header extends React.Component {
render() {
return (
<MyContext.Consumer>
{ value => { console.log(value);
return (
<Text style={styles.text}>
Welcome {value}
</Text>)
}
}
</MyContext.Consumer>
)
}
}
const styles = StyleSheet.create({
text: {
fontSize: 24,
alignSelf: 'center',
alignContent:'center',
},
});
The App simply prints Welcome on the screen. I would like it to print the entire state contents like isAuthenticate, name & email. What am I doing wrong?
value is an object so you'll need to access the individual props inside it:Welcome {value?.user?.name} or replace Welcome {value} with Welcome {JSON.stringify(value)}

NextJs getServerSideProps() never calls api

I have created a nextjs page and inside the page, there is getServerSideProps that calls API to fetch data.
The problem is that getServerSideProps never calls API and returns a response error 403 Unauthorized
nextjs is serving data from .next folder and returns a JSON response and instead of calling API it calls this URL http://localhost:3000/_next/data/development/contacts.json
This is my code
import React, { useState, useEffect } from "react"
import {
Card,
CardHeader,
CardFooter,
Container,
Row,
Button
} from "reactstrap"
import AdminLayout from "../components/layouts/AdminLayout"
import PropTypes from "prop-types"
import TablePagination from "../components/common/TablePagination"
import { fetchData } from "../api"
import { toast } from "react-toastify"
import { useSession } from "../context/SessionContext"
import ProtectPage from "../hocs/ProtectPage"
import { getContacts } from "../api/contacts"
import ContactsTable from "../components/contacts/ContactsTable"
const Contacts = ({ initialContacts, initialPagination, error }) => {
const [contacts, setContacts] = useState(initialContacts)
const [pagination, setPagination] = useState(initialPagination)
const session = useSession()
const handlePagination = async (page) => {
fetchData({
apiMethod: () => getContacts({ page }),
callback: (res, error) => {
if (error || !res) {
toast("Error loading Contacts")
} else {
setContacts(res.data)
setPagination(res.pagination)
}
session.loadingQueue.dequeue()
}
})
}
useEffect(() => {
setContacts(initialContacts)
setPagination(initialPagination)
}, [initialContacts, initialPagination])
return (
<AdminLayout>
{/* Page content */}
<Container className="mt--7" fluid>
<Row>
<div className="col">
<Card className="shadow">
<CardHeader className="border-0">
<Row className="justify-content-between w-100 m-0">
<h3 className="mb-0">Contacts</h3>
</Row>
</CardHeader>
<ContactsTable contacts={contacts ?? []} />
<CardFooter className="py-4">
<TablePagination
{...pagination}
handlePagination={handlePagination}
/>
</CardFooter>
</Card>
</div>
</Row>
</Container>
</AdminLayout>
)
}
Contacts.propTypes = {
initialContacts: PropTypes.array.isRequired,
initialPagination: PropTypes.object.isRequired
}
export async function getServerSideProps(ctx) {
try {
const contactsRes = await getContacts({})
const { data: initialContacts, pagination: initialPagination } =
contactsRes.data
return {
props: {
initialContacts,
initialPagination
}
}
} catch (error) {
return {
props: {
initialContacts: [],
initialPagination: {},
error: true
}
}
}
}
export default ProtectPage(Contacts)
I tried to disable cache and nothing worked. still serving JSON files.
console.log(contactsRes) in getServerSideProps
Or
call your api from getServerSideProps (await fetch(your_path))

Warning: Invalid DOM property `class`. Did you mean `className`? in a react-dom.development.js file

every since i run my website locally i keep getting this error along with two other errors. The problem is that i do understand the errors but they are pointing to a file called "react-dom.development.js 86" which i dont even have and cant find the following file in my vs code.
Here is a picture of the errors i have been getting in the console:
This is my pingbutton.js file:-
import React, { useState } from "react";
import "./Pingbutton.scss";
import "./Pingbutton.css";
import { gsap } from "gsap";
// import find_my_iphonen from "./Users/omarfares/Desktop/PINGOMAR/ping-omar-Backend/app.js";
import axios from "axios";
class Pingbutton extends React.Component {
constructor(props) {
super(props);
this.state = { val: "Here is your message omar!: " };
}
handleSubmit = () => {
console.log("its running");
let databody = {
message: this.state.val,
};
console.log(" the message is :" + databody.message);
console.log(" the message is :" + this.state.val);
return fetch("http://localhost:5000/stored", {
method: "POST",
body: JSON.stringify(databody),
headers: {
"Content-Type": "application/json",
},
})
.then((res) => res.json())
.then((data) => console.log(data));
};
changeval = () => {
let newval = this.textInput.value;
console.log("submitted");
this.setState({ val: newval });
console.log(this.state.val);
};
render() {
return (
<div className="ok2">
<textarea
className="message"
ref={(input) => {
this.textInput = input;
}}
type="text"
placeholder="Write me somthing!. Also, double click to ping:) "
// value={this.state.val}
></textarea>
<button
className="button"
onClick={() => {
this.magic();
this.changeval();
this.handleSubmit(); //animation + //pinging the phone
// this.handleButtonClick(); //setVal(() => ""); //sets the value of the box to empty
}}
></button>
</div>
);
}
}
export default Pingbutton;
im using react js, node js/mac
Thank you.
It seems like you wrote class instead of className. To set class in React, use className. And also, in the second error it looks like you put the body tag in a div tag.

How to get the links in Draft js in read only mode?

I am creating a simple blog writing application. I am using Draft.js as an editor. I am able to create the link while writing the blog but when I go into read mode all the links are missing. Here are the React code for writing and reading the blogs. For simplicity I am storing the editorState/data in localStorage. Here is WriteBlog.js file
import React, { Component } from "react";
import Editor, { createEditorStateWithText } from "draft-js-plugins-editor";
import createInlineToolbarPlugin from "draft-js-inline-toolbar-plugin";
import createLinkPlugin from "draft-js-anchor-plugin";
import createToolbarPlugin, { Separator } from "draft-js-static-toolbar-plugin";
import {
convertFromRaw,
EditorState,
RichUtils,
AtomicBlockUtils,
convertToRaw
} from "draft-js";
import { ItalicButton, BoldButton, UnderlineButton } from "draft-js-buttons";
import editorStyles from "./editorStyles.css";
import buttonStyles from "./buttonStyles.css";
import toolbarStyles from "./toolbarStyles.css";
import linkStyles from "./linkStyles.css";
import "draft-js-alignment-plugin/lib/plugin.css";
const staticToolbarPlugin = createToolbarPlugin();
const linkPlugin = createLinkPlugin({
theme: linkStyles,
placeholder: "http://…"
});
const inlineToolbarPlugin = createInlineToolbarPlugin({
theme: { buttonStyles, toolbarStyles }
});
const { Toolbar } = staticToolbarPlugin;
const { InlineToolbar } = inlineToolbarPlugin;
const plugins = [staticToolbarPlugin, linkPlugin];
const text =
"Try selecting a part of this text and click on the link button in the toolbar that appears …";
export default class WriteBlog extends Component {
state = {
editorState: createEditorStateWithText(text)
};
onChange = editorState => {
let contentRaw = convertToRaw(this.state.editorState.getCurrentContent());
const stringyfyRawContent = JSON.stringify(contentRaw);
localStorage.setItem("blogcontent", JSON.stringify(contentRaw));
this.setState({
editorState
});
};
handleSave = async e => {
e.preventDefault();
// await this.setState({
// saveblog: 1,
// publish: 0
// });
// this.props.create_post(this.state);
// console.log("save state", this.state);
localStorage.setItem(
"blogsaveblog",
JSON.stringify(this.state.editorState)
);
};
focus = () => this.editor.focus();
render() {
return (
<div className={editorStyles.editor} onClick={this.focus}>
<form onSubmit={this.handleSave}>
<Editor
editorState={this.state.editorState}
onChange={this.onChange}
plugins={plugins}
ref={element => {
this.editor = element;
}}
/>
<Toolbar>
{// may be use React.Fragment instead of div to improve perfomance after React 16
externalProps => (
<div>
<BoldButton {...externalProps} />
<ItalicButton {...externalProps} />
<UnderlineButton {...externalProps} />
<linkPlugin.LinkButton {...externalProps} />
</div>
)}
</Toolbar>
<button
type="submit"
className="btn btn-primary"
style={{ margin: "10px" }}
>
Save
</button>
</form>
</div>
);
}
}
and here is ReadBlog.js file
import React, { Component } from "react";
import Editor, { createEditorStateWithText } from "draft-js-plugins-editor";
import createInlineToolbarPlugin from "draft-js-inline-toolbar-plugin";
import createLinkPlugin from "draft-js-anchor-plugin";
import createToolbarPlugin, { Separator } from "draft-js-static-toolbar-plugin";
import { convertFromRaw, EditorState, convertToRaw } from "draft-js";
import { ItalicButton, BoldButton, UnderlineButton } from "draft-js-buttons";
import editorStyles from "./editorStyles.css";
import buttonStyles from "./buttonStyles.css";
import toolbarStyles from "./toolbarStyles.css";
import linkStyles from "./linkStyles.css";
import "draft-js-alignment-plugin/lib/plugin.css";
const staticToolbarPlugin = createToolbarPlugin();
const linkPlugin = createLinkPlugin({
theme: linkStyles,
placeholder: "http://…"
});
const inlineToolbarPlugin = createInlineToolbarPlugin({
theme: { buttonStyles, toolbarStyles }
});
const { Toolbar } = staticToolbarPlugin;
const { InlineToolbar } = inlineToolbarPlugin;
const plugins = [staticToolbarPlugin, linkPlugin];
const text =
"Try selecting a part of this text and click on the link button in the toolbar that appears …";
export default class ReadBlog extends Component {
state = {
editorState: createEditorStateWithText(text)
};
componentDidMount = () => {
const rawContentFromdb = convertFromRaw(
JSON.parse(localStorage.getItem("blogcontent"))
);
const initialEditorStatedb = EditorState.createWithContent(
rawContentFromdb
);
this.setState({ editorState: initialEditorStatedb });
};
focus = () => this.editor.focus();
render() {
return (
<div className={editorStyles.editor} onClick={this.focus}>
<Editor
editorState={this.state.editorState}
plugins={plugins}
readOnly={true}
ref={element => {
this.editor = element;
}}
/>
</div>
);
}
}
I know this is super late, but you are not adding the decorator which is why this is not working. In this case, you'll want to use compositeDecorator to build your decorator object, and initialize the react state with it.
const decorator = new CompositeDecorator([
{
strategy: linkStrategy,
component: LinkDecorator,
},
]);
const [editorState, setEditorState] = useState(() =>
EditorState.createWithContent(initialContentState, decorator),
);

pass state as props in component child in React

I get data from a local server, catch them with axios.get, and save them in my state. It's ok, but when i want to pass it as props in an component child, KABOOM! Doesn't work.
I'm looking for a solution, I think it's lyfecycle problem but i'm not sure.
App.js
import React, { Component } from 'react';
import './style/App.css';
import axios from 'axios'
import Table from './Components/Table'
class App extends Component {
state = {
tabData: [],
}
componentWillMount = () => {
this.getDataFromServer()
}
getDataFromServer = () => {
axios.get("http://localhost:8000")
.then((response) => {
const twentyObj = response.data.splice(-20);
this.setState({
tabData:twentyObj
})
console.log(this.state.tabData)
})
.catch(function (error) {
console.log(error);
})
}
render() {
return (
<div className="App">
<Table stateData={this.state.tabData}/>
</div>
);
}
}
export default App;
Developer Tools Browser say:
TypeError: _this.props is undefined
(for this.props.tabData.map in Table.js)
Table.js
import React from 'react';
import Cell from './Cell'
const Table = (props) => {
return(
<div>
{this.props.tabData.map( item =>
<Cell key={item.index}
time={item.timestamp}
nasdaq={item.stocks.NASDAQ}
cac40={item.stocks.CAC40}/>
)}
</div>
)
}
export default Table;
Table is functional component this has no value there and thats what the error message is telling you.
You should use props.tabData and not this.props.tabData
UPDATE:
Here you are passing it as stateData and not tabData Try props.stateData

Resources