I need such an editor on react https://cloverhearts.github.io/quilljs-markdown/ , as you can see in it you can put markdown characters directly into the text.
import React from "react";
import ReactQuill, {Quill} from 'react-quill';
import 'react-quill/dist/quill.snow.css';
const QuillMakrdown = require('quilljs-markdown');
interface UIQuillEditorDemoProps { }
interface UIQuillEditorDemoState { text: string; }
export class UIQuillEditorDemo extends React.Component<UIQuillEditorDemoProps, UIQuillEditorDemoState> {
constructor(props: UIQuillEditorDemoProps) {
super(props);
this.state = { text: "" }
}
handleChange = (text: any) => {
this.setState({ text });
}
modules = {...}
formats = [...]
convertToMarkdown() {
// const turndownService = new TurndownService();
// this.setState({ text: turndownService.turndown(this.state.text) });
const editor = new Quill('#editor', {
theme: 'snow'
})
new QuillMakrdown(editor);
}
render() {
return (
<div className='d-flex flex-column'>
<ReactQuill style={{ height: '300px', marginBottom: '50px' }}
theme="snow" modules={this.modules} formats={this.formats}
placeholder={"Write something..."}
onChange={this.handleChange}
/>
<div>
<Button onClick={() => this.convertToMarkdown()}>Convert To Markdown</Button>
<div id="editor"></div>
<RenderToMarkDown text={this.state.text} />
</div>
</div>
);
}
}
I found https://www.npmjs.com/package/react-quill this quilljs for react, but I don't know how to combine it with markdown https://www.npmjs.com/package/quilljs-markdown can anyone help?
Related
I try to learn React JS, however, I stumbled over a problem I can't solve. I try to use an API to get a value of something and show the value as a simple text, but the text is not updating even tho the Data gets correctly log in console.
The Code of my App.js is
import React, { Component } from "react";
import { Button } from "#material-ui/core";
import { Image } from "react-bootstrap";
import albedo from "#albedo-link/intent/lib/albedo.intent";
import albedologo from "./albedo.png";
class LogInWithAlbedo extends Component {
constructor(props) {
super(props);
this.state = {
value: null
};
}
Albedo() {
albedo.publicKey({}).then((res) => {
const { intent, pubkey, signature, signed_message } = res;
console.log({ intent, pubkey, signature, signed_message });
this.setState((currentState) => {
return { value: pubkey };
});
});
}
render() {
const { pubkey } = this.state;
return (
<div>
<div>
<Button
style={{ width: "207px", height: "40px" }}
variant="contained"
color="default"
onClick={this.Albedo.bind(this)}
>
Login With <Image style={{ width: "55px" }} src={albedologo} />
</Button>
<h2>It is {pubkey}.</h2>
</div>
</div>
);
}
}
export default LogInWithAlbedo;
You can also see it here:
https://codesandbox.io/s/vigilant-star-ntqv7
I'm looking for information in a database, in an app with react. In the actions.js file I can see the response.data data, when I put a console.table.
But even exporting, when I try to display the information, the variable's value comes as undefined.
I've already looked at the original file I'm using to learn, and I couldn't see where the error is.
action.js
import { CLEAR_SEARCH, SEARCH_CUSTOMERS } from "./actionTypes";
import Axios from "axios";
import { SEARCH_CUSTOMERS_URL } from "../../configs";
export const searchCustomers = (lat, lng, query) => dispatch => {
Axios.post(SEARCH_CUSTOMERS_URL, {
q: query,
})
.then(response => {
const customers = response.data;
console.log( "services/searchCustomers/actions.js, line 30" );
console.log( customers ); //ok, showing data
return dispatch({ type: SEARCH_CUSTOMERS, payload: customers });
})
.catch(function(error) {
console.log(error);
});
};
export const clearSearch = () => dispatch => {
const customers = [];
return dispatch({ type: CLEAR_SEARCH, payload: customers });
};
reducer.js
import { CLEAR_SEARCH, SEARCH_CUSTOMERS } from "./actionTypes";
const initialState = {
customers: []
};
export default function(state = initialState, action) {
switch (action.type) {
case SEARCH_CUSTOMERS:
return { ...state, customers: action.payload };
case CLEAR_SEARCH:
return { ...state, customers: action.payload };
default:
return state;
}
}
actionTypes.js
export const SEARCH_CUSTOMERS = "SEARCH_CUSTOMERS";
export const CLEAR_SEARCH = "CLEAR_SEARCH";
index.js
import React, { Component } from "react";
import { clearSearch, searchCustomers } from "../../../../services/searchCustomers/actions";
import Dialog from "#material-ui/core/Dialog";
import DelayLink from "../../../helpers/delayLink";
import Ink from "react-ink";
import LazyLoad from "react-lazyload";
import { Redirect } from "react-router";
import CustomerSearch from "../../CustomerSearch";
import CustomerSearchList from "../CustomerSearchList";
import { connect } from "react-redux";
import { debounce } from "../../../helpers/debounce";
import ContentLoader from "react-content-loader";
class SelectCustomer extends Component {
state = {
open: false,
queryLengthError: false,
loading: false,
showBgImage: true,
nothingFound: false,
};
handleCustomerSearch = debounce((query) => {
// call to searchCustomers search API
if (query.length >= 3) {
this.props.searchCustomers(
JSON.parse(localStorage.getItem("userSetAddress")).lat,
JSON.parse(localStorage.getItem("userSetAddress")).lng,
query
);
console.table( this.props ); //customers is undefined
this.setState({
queryLengthError: false,
loading: true,
nothingFound: false,
});
} else {
this.setState({ queryLengthError: true });
}
}, 400);
componentDidMount() {
//others
}
componentWillUnmount() {
//others
}
componentWillReceiveProps(nextProps) {
//this.props.customers is undefined
if (this.props.customers !== nextProps.customers) {
this.setState({ loading: false });
}
// console.log(nextProps.customers.length);
if (nextProps.customers) {
if (nextProps.customers.length === 0 ) {
this.setState({ showBgImage: true, nothingFound: true });
} else {
this.setState({ showBgImage: false, nothingFound: false });
}
}
//Overlay/Dialog.
if (nextProps.confirmSelectCustomerOpen === false) {
this.setState({ open: false });
}
if (nextProps.confirmSelectCustomerOpen === true) {
this.setState({ open: true });
}
}
//Overlay/Dialog
handleClose = () => {
this.setState({ open: false });
};
render() {
return (
<React.Fragment>
<Dialog
fullWidth={true}
fullScreen={false}
open={this.state.open}
onClose={this.handleClose}
style={{ width: "100%", margin: "auto" }}
PaperProps={{ style: { backgroundColor: "#fff", borderRadius: "10px" } }}
>
{this.state.queryLengthError && (
<div className="auth-error" style={{ marginBottom: "4rem" }}>
<div className="">{localStorage.getItem("searchAtleastThreeCharsMsg")}</div>
</div>
)}
<CustomerSearch searchFunction={this.handleCustomerSearch} />
{this.state.loading && (
{/*loading*/}
)}
{/* Here Should list customers */}
{this.props.customers && this.props.customers.length > 0 && (
<CustomerSearchList customers={this.props.customers} />
)}
{this.state.showBgImage && (
<div className="d-flex justify-content-center mt-100">
<img
className="img-fluid explore-bg"
src="/assets/img/various/explore-bg.png"
alt={localStorage.getItem("restaurantSearchPlaceholder")}
/>
</div>
)}
{this.state.nothingFound && (
<div className="auth-error" style={{ marginBottom: "4rem" }}>
<div className="error-shake">{localStorage.getItem("exploreNoResults")}</div>
</div>
)}
</Dialog>
</React.Fragment>
);
}
}
const mapStateToProps = (state) => ({
customers: state.customers
});
export default connect(
mapStateToProps,
{ searchCustomers, clearSearch }
)(SelectCustomer);
CustomerSearch/index.js
import React, { Component } from "react";
import Ink from "react-ink";
class CustomerSearch extends Component {
state = {
customer: ""
};
componentDidMount() {
this.searchInput.focus();
}
static contextTypes = {
router: () => null
};
handleInputChange = e => {
this.setState({ customer: e.target.value });
this.props.searchFunction(e.target.value);
};
render() {
return (
<React.Fragment>
<div className="col-12 p-0">
<div className="block m-0">
<div className="block-content p-0">
<div className="input-group search-box">
<div className="input-group-prepend">
<button
type="button"
className="btn search-navs-btns"
style={{ position: "relative" }}
onClick={this.context.router.history.goBack}
>
<i className="si si-arrow-left" />
<Ink duration="500" />
</button>
</div>
{/*
placeholder do input
{localStorage.getItem("restaurantSearchPlaceholder")}
*/}
<input
type="text"
className="form-control search-input"
placeholder="Pesquisar Cliente"
value={this.state.customer}
onChange={this.handleInputChange}
ref={input => {
this.searchInput = input;
}}
/>
<div className="input-group-append">
<button type="submit" className="btn search-navs-btns" style={{ position: "relative" }}>
<i className="si si-magnifier" />
<Ink duration="500" />
</button>
</div>
</div>
</div>
</div>
</div>
</React.Fragment>
);
}
}
export default CustomerSearch;
CustomerSearchList/index.js
import React, { Component } from "react";
import DelayLink from "../../../helpers/delayLink";
import Ink from "react-ink";
import LazyLoad from "react-lazyload";
class CustomerSearchList extends Component {
render() {
const { customers } = this.props;
return (
<React.Fragment>
{customers.map((customer) => (
<div key={customer.id} className="col-xs-12">
<DelayLink
to={"../stores/" + customer.id}
delay={200}
className="block block-link-shadow text-center light-bottom-border"
>
<Ink duration="500" />
</DelayLink>
</div>
))}
</React.Fragment>
);
}
}
export default CustomerSearchList;
reducers.js
import { combineReducers } from "redux";
....
....
import customerSearchReducer from "./searchCustomers/reducer";
import addressesReducer from "./addresses/reducer";
....
....
export default combineReducers({
...
customers: customerSearchReducer,
addresses: addressesReducer,
...
});
SEARCH_CUSTOMERS_URL - URL to php, get data:
$response = ['customers' => $customers];
Output customers: Array(3)
0: {id: 2, name: "Customer 1", email: "customer1#gmail.com"}
1: {id: 3, name: "Customer 2", email: "customer2#gmail.com"}
2: {id: 4, name: "Customer 3", email: "customer3#gmail.com"}
It's 3 days racking my brain. I did some research but I couldn't solve the problem. I'm new to react/reduce and was trying to figure it out based on this script.
As per comments... add searchCustomer reducer to rootReducer.
I use Two package
slate-react and emoji-mart
I want to when choose an Emoji , it puts on my editor.
import React from "react";
import { render } from "react-dom";
import { Editor } from "slate-react";
import { initialValue } from "./initialValue";
// Define our app...
class MyEditor extends React.Component {
// Set the initial value when the app is first constructed.
state = {
value: initialValue
};
// On change, update the app's React state with the new editor value.
onChange = ({ value }) => {
this.setState({ value });
};
onKeyDown = (event, change) => {
// This used to have stuff in it, but I moved it all to plugins.
};
clickMe=()=>{
this.setState({ value : this.state.value });
};
// Render the editor.
render() {
return (
<div>
<h1 onClick={this.clickMe}>Slate Editor Demo</h1>
<div style={{ border: "1px solid black", padding: "1em" }}>
<Editor
value={this.state.value}
onChange={this.onChange}
onKeyDown={this.onKeyDown}
renderNode={this.renderNode}
spellCheck={false}
/>
</div>
</div>
);
}
}
export default MyEditor;
import React,{useState} from 'react';
import 'emoji-mart/css/emoji-mart.css';
import { Picker } from 'emoji-mart';
function Emoji() {
const [emoji,setEmoji] = useState(null);
const addEmoji = (e) => {
setEmoji(e.native)
};
return <Picker onSelect={addEmoji} />
}
export default Emoji;
Try passing the editor ref to picker. Then in Emoji component in addEmoji method, try editorRef.current.InsertText(e.native). After hours of trying to solve this:
const YourTextEditor = props => {
const editor = createEditor();
const addEmoji = async emoji => {
await setTimeout(() => {
editor.focus();
}, 100);
editor.insertText(emoji.native);
};
return (
<>
<Editor
value={initialValue}
/>
<Emoji addEmoji={addEmoji} />
</>
);
};
const Emoji = props => {
return (<Picker onSelect={e => props.addEmoji(e)} />);
};
I'm using the official Semantic UI React components to create a web application. I have a form on a search page, which contains an input field.
import React from 'react'
import {Form} from "semantic-ui-react";
import RadiusOfSearchInput from "./RadiusOfSearchInput";
const NearbyShopsSearchForm = (props) => {
const { onSubmit, size, action, onChange, value, style } = props
return (
<Form onSubmit={onSubmit}>
<RadiusOfSearchInput size={size}
action={action}
onChange={onChange}
value={value}
style={style} />
</Form>
)
}
export default NearbyShopsSearchForm
The component that uses the form is as shown below:
import React, { Component } from 'react'
import {Menu, Container, Segment} from 'semantic-ui-react'
import ShopCardList from "../components/ShopCardList";
import axios from 'axios';
import NearbyShopsSearchForm from "../components/NearbyShopsSearchForm";
class NearbyShopsPage extends Component {
constructor(props) {
super(props)
this.state = {
radius: '',
shops: []
}
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
}
handleChange = (e, { value } ) => {
this.setState({ radius: value })
}
handleSubmit = (e, data) => {
const { radius } = this.state
const url = `/api/shops/#33.846978,-6.775816,${radius}`
axios.get(url)
.then((response) => {
this.setState({ shops: response.data })
})
.catch((error) => {
console.log(error)
})
e.preventDefault()
}
render() {
const { radius } = this.state
return (
<Segment basic>
<Menu fixed='top' size='huge' borderless>
<Menu.Item>
<NearbyShopsSearchForm onSubmit={this.handleSubmit}
size='large'
action={{ color: 'teal', content: 'Search', size: 'small' }}
onChange={this.handleChange}
value={radius}
style={{ width: '17.5em' }} />
</Menu.Item>
</Menu>
<Container style={{ marginTop: '5.5em' }}>
<ShopCardList shops={this.state.shops}/>
</Container>
</Segment>
)
}
}
export default NearbyShopsPage
I want to validate the form so it won't submit values other than decimals, which are valid values to represent a distance. I didn't find validation support in the SUIR official documentation. I'm aware of the redux-form possibility, but i fail to implement it correctly. what's the recommended and simplest way to implement the data validation feature?
I am new to react. I am displaying 10 question with 3 answers per question. Im having trouble capturing which answers they choose per question and storing the value as a array. Here is my code. Im not sure but I think i will need a handle change and a handle submit and bind them to the answers.
import React, { Component } from 'react';
import {
BrowserRouter as Router,
Route,
Link,
Redirect,
withRouter
} from 'react-router-dom';
import axios from 'axios';
import AnswerOption from "./answersContent";
import RaisedButton from 'material-ui/RaisedButton';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
const styles = {
display: 'flex',
justifyContent: "center"
};
const style = {
margin: 15,
};
const Content = {
padding: 10,
margin: 10,
backgroundColor: "",
color: "",
display: "inline-block",
fontFamily: "monospace",
fontSize: "18",
};
const answ ={
listStyle: 'none'
};
class Questions extends Component {
constructor(props) {
super(props);
this.state = {
redirect: "",
user: "",
questions: [],
answers: []
}
}
componentDidMount() {
console.log(this.props.user);
axios.post('/questions')
.then((response) => {
console.log(response);
if (response.status === 200) {
console.log("successfull");
// self.setState({ user: response.data.user.id});
this.setState({user: this.props.user});
this.setState({redirect: false});
this.setState ({ questions :
response.data.surveyQuestions})
}
})
.catch(function (error) {
console.log(error);
});
}
handleClick(event){
const payload={
"answers": this.state.answers
};
console.log(payload)
}
render(){
const { redirect } = this.state;
if (redirect) {
return <Redirect to='/login'/>;
}
return (
<div className="dashboard" style={styles}>
< MuiThemeProvider>
<div style={Content}>
<h1>Welcome to The Well-Stocked Stork!</h1>
<br />
{this.state.questions.map((quest) => (
<p> {quest.id}. {quest.question}
<ul style={answ}>
<li> <input type="radio" name=
{quest.surveyAnswers[0].body} value={quest.surveyAnswers[0].value}
onChange = {(event,value) => this.setState({answers:
quest.surveyAnswers[0].value})} />{quest.surveyAnswers[0].body}</li>
<li> <input type="radio" name=
{quest.surveyAnswers[1].body} value={quest.surveyAnswers[1].value}
onChange = {(event,value) => this.setState({answers:
quest.surveyAnswers[1].value})} />{quest.surveyAnswers[1].body}</li>
<li> <input type="radio" name=
{quest.surveyAnswers[2].body} value={quest.surveyAnswers[2].value}
onChange = {(event,value) => this.setState({answers:
quest.surveyAnswers[2].value})} />{quest.surveyAnswers[2].body}</li>
</ul>
</p>
))}
<RaisedButton label="Submit" primary={true} style=
{style} onClick={(event) => this.handleClick(event)}/>
</div>
</MuiThemeProvider>
</div>
)
}
}
export default Questions;
You are right to handle change but you are missing one thing. You should bind you handleClick method in the constructor. Something like this.handleClick = this.handleClick.bind(this) otherwise you will get an error something ..state is not defined...