#How to render raw html in react
there is a module html-to-react but I suggest you using dangerouslySetInnerHTML
1 |
<div dangerouslySetInnerHTML={{ __html: patent && patent.nationalPhaseContent }} /> |
How to stop scrolling when is dialog
Here is written something link you have to do like that
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
onClickAddWork = e => { e.preventDefault() document.body.style.overflow = 'hidden'; this.setState({ addWork: true }) } onClickCreateAddWork = e => { e.preventDefault() document.body.style.overflow = 'unset'; this.setState({ addWork: false }) } |
How to insert google invisible recaptcha to react
so it is very easy, at firs we have to include a script to the head section. To do this we’are going to use react-helmet module
1 |
npm i react-helmet |
and put code to our component
1 2 3 4 5 6 7 8 9 |
import { Helmet } from 'react-helmet' ... ... <Helmet> <title>Log in</title> <script src="https://www.google.com/recaptcha/api.js" async defer></script> </Helmet> ... |
and then include a div block that is used to stick captcha
1 2 3 4 5 6 7 |
... <div className="g-recaptcha" data-sitekey={Config.siteKey2} data-callback="getRecaptchaValue" data-size="invisible"> </div> ... |
and then add a callback function in my case I’m using getRecaptchaValue that is stuck to the window object because it should be available. The getRecaptchaValue function we have to implement inside the function that is handle click of the form. In my case the handler of form is a Formik onSubmit property, so I implemented the getRecapthcaValue function in it. Here is the code of onSubmit property
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
... onSubmit={(values, actions) => { actions.setSubmitting(false) this.setState({ isFetching: true }) window.grecaptcha.execute(); // run the captcha // this is the function that is a closure window.getRecaptchaValue = (g_token) => { window.grecaptcha.reset() console.log('Captcha g_token:', g_token); fetch(`/api/v1/login/`, { method: 'POST', headers: { // 'Content-Type': 'application/json' 'Content-Type': 'application/x-www-form-urlencoded' }, body: `username=${values.username}&password=${values.password}&g_token=${g_token}` }) .then(r => { this.setState({ isFetching: false }) if (!r.ok) { console.log('r = ', r); actions.setStatus({ error: 'The server unavailable' }); actions.setSubmitting(false); } return r.json() }) .then(json => { console.log('json = ', json); console.log('json.error = ', json.error); if (json.error) { actions.setStatus({ error: json.error }) } if (json.token) { const { dispatch } = this.props dispatch(a.setIdLoginToken(json.user.id, json.user.login, json.token, values.rememberMe || false, json.avatar )) } }) .catch(error => { console.log("error = " + error); }) } }} ... |
that’s it
How to insert google visible recaptcha
We know how to insert invisible recaptcha, now it time inserted visible checkbox captcha. We do almost the same as described here only without callback.
1. add div block to the form
1 2 3 4 5 6 7 8 |
<div class="g-recaptcha" data-sitekey={Config.siteKey2} data-callback="getRecaptchaValue" data-theme="dark" data-size="normal" > </div> |
2. using react-helmet include google to the head
1 2 3 4 |
<Helmet> <title>Publish</title> <script src="https://www.google.com/recaptcha/api.js" async defer></script> </Helmet> |
3. in onSubmit formik’s method we can get the value by using next code
1 |
const g_token = window.grecaptcha.getResponse() |
and then pass the response to the server.
The callback won’t work, so do not use it
That’s it, Pass the g_token to the server and verify.
How to prevent from rerendering element a few times
I have a problem when loading files to a server I added an image file and it always rerendered and flickering so it was not attractive and bad for eyes. So how I managed to solve the problem? In react is a special method calls ‘shouldComponentUpdate‘. It accepts two arguments nextProps and nextState, so that we can check out what is changed in the next state and props use such conditions
1 2 3 4 5 6 7 8 9 |
if (nextProps.[somevar] === this.props.[somevar]) { return false } // or if (nextState.[somevar] === this.state.[somevar]) { return false } |
Here is a real example where I used it with in the Thumb component
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
import React from 'react' class Thumb extends React.Component { state = { loading: false, thumb: undefined, file: undefined, }; shouldComponentUpdate(nextProps, nextState) { if (nextProps.file === this.props.file && this.state.loading === false) { return false } return true } componentWillReceiveProps(nextProps) { if(nextProps.file === this.props.file) { return; } if (!nextProps.file) { return; } this.setState({ loading: true }, () => { let reader = new FileReader(); reader.onloadend = () => { // console.log('reader.result = ', reader.result); this.setState({ loading: false, thumb: reader.result }); }; reader.readAsDataURL(nextProps.file); }); } render() { const { file } = this.props; const { loading, thumb } = this.state; if (!file) { return null; } if (loading) { return <p>loading...</p>; } return (<img src={thumb} alt={file.name} className="img-thumbnail mt-2" height={100} width={100} />); } } export default Thumb |
How to get image width and height in the React with Formik
Sometimes you have to check out the image width and height, to get them you should create the image
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<input ref={input => { this.thumbnail = input }} name="thumbnail" type="file" onChange={(event) => { setFieldValue("thumbnail", event.currentTarget.files[0]); touched.thumbnail = true // check the image with and height var _URL = window.URL || window.webkitURL var file, img if ((file = event.currentTarget.files[0])) { img = new Image() img.onload = function() { console.log(this.width + " " + this.height) setFieldValue("thumbnailWithAndHeight", { width: this.width, height: this.height }); } img.src = _URL.createObjectURL(file) } }} /> |
so we assigned the width and height to the thumbnailWithAndHeight property and then we check it in the Formik’s validate function
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
if ( values.thumbnail.type === 'image/jpeg' || values.thumbnail.type === 'image/png' || values.thumbnail.type === 'image/gif') { if (values.thumbnail.size > Config.thumbnailSize) { errors.thumbnail = `The thumbnail couldn't be more than 1Mb` } if (values.thumbnailWithAndHeight.height) { if (+values.thumbnailWithAndHeight.width !== 200 || +values.thumbnailWithAndHeight.height !== 200) { errors.thumbnail = errors.thumbnail ? errors.thumbnail + "<br>" : '' errors.thumbnail += `The thumbnail should be 200x200 pixels` } } } else if (values.thumbnail.type) { errors.thumbnail = `The thumnbail type could be jpeg png or gif` } |
that’s it
How to add radio buttons on the form with Formik
here is an example link
I make a simple usage. We have to create a RadioButton
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
// Radio input const RadioButton = ({ field: { name, value, onChange, onBlur }, id, label, className, ...props }) => { console.log('field = ', name, value); return ( <div> <input name={name} id={id} type="radio" value={id} // could be something else for output? checked={id === value} onChange={onChange} onBlur={onBlur} className={"radio-button"} {...props} /> <label htmlFor={id}>{label}</label> </div> ); }; |
and than put it to the Formik’s render property like that
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<div className="formGroup gender"> <label>Gender: </label> <div onChange={this.onChangeGender}> <label> <Field component={RadioButton} name="gender" id="male" label="Male" /> </label> <label> <Field component={RadioButton} name="gender" id="female" label="Female" /> </label> </div> </div> |
and in the initialValue pass gender: ‘male’, and that’s it we’ll see selected by default mail radio button.
That’s it
How to create a complex component with in React with Formik
Sometimes we have to create a complex component like with Formik that will have a few input field. First of all it has one input than when we specified that input it will add a few more and so on. This is a complex component. To work it out we have to overload some properties namely onChange by using setFieldValue
setFieldValue is a function that assign a value to the Formik state.
Let’s look at a trivial example, here is a Test component
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
class Test extends React.Component { constructor(props) { super(props) this.state = { value1: '', value2: '' } } onChangeHandler1 = e => { const { field: { onChange }, form: { setFieldValue } } = this.props this.setState({ value1: e.target.value }) setFieldValue('test', { value1: e.target.value, value2: this.state.value2 }) } onChangeHandler2 = e => { const { field: { onChange }, form: { setFieldValue } } = this.props this.setState({ value2: e.target.value }) setFieldValue('test', { value1: this.state.value1, value2: e.target.value }) } render() { let { field: { name, value, onChange, onBlur }, form: { errors, touched, setFieldValue }, id, label, className, } = this.props console.log('###this.props = ', this.props); // value="bla-bla" return ( <div> <input // name={name} value={this.state.value1} onChange={this.onChangeHandler1} onBlur={onBlur} /> <input value={this.state.value2} onChange={this.onChangeHandler2} onBlur={onBlur} /> {touched[name] && <div className="error">{errors[name]}</div>} </div> ) } } |
it outputs two inputs and we want to get both values to the one variable test in our Formik. The inner form could be more complex and consist of lots of elements. So on the onChange we call the setFieldValue function to assign an object to the test of Formik. In the Formik’s render method we have such code
1 2 3 4 |
<Field component={Test} name="test" /> |
and
1 2 3 |
initialValues={{ test: 'hello' }} |
and in the test variable on the onSubmit method we’ll get an object
1 2 3 4 |
onSubmit={(values, actions) => { actions.setSubmitting(false) console.log('@@@values = ', values); }} |
that’s it
How to add to the Formik CheckBox component ref.
It is impossible to pass ref to the Formik’s Field component, If you do like that
1 2 3 4 5 6 7 |
<Field ref={input => this.logInAndPublish = input} component={Checkbox} id="logInAndPublish" type="checkbox" name="logInAndPublish" /> |
you’ll get a warning
Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
and here is a description what to do forwarding refs
We can’t pass to the Field a ref because it is a third party libs, So we can use global variable window, stick to it a ref from the components like that
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
// Checkbox input class CheckboxWithGlobalRefs extends React.Component { constructor(props) { super(props) } render() { const { field: { name, value, onChange, onBlur }, form: { errors, touched, setFieldValue }, id, label, className, ref, } = this.props // console.log('value = ', value); // console.log('name = ', name); return ( <div className={"formGroup " + id}> <input ref={input => window[name] = input} name={name} id={id} type="checkbox" value={id} checked={value} onChange={onChange} onBlur={onBlur} className={className} {...this.props} /> <label htmlFor={id}>{label}</label> {touched[name] && <div className="error">{errors[name]}</div>} </div> ); } }; |
and then it will accessible from the anywhere in code like below
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<Field component={CheckboxWithGlobalRefs} id="publishAsGuest" type="checkbox" name="publishAsGuest" onChange={e => { console.log('window.publishAsGuest = ', window.publishAsGuest); console.log('window.logInAndPublish = ', window.logInAndPublish); setFieldValue('publishAsGuest', !values.publishAsGuest) setFieldValue('logInAndPublish', false) window.logInAndPublish.checked = ''; }} /> |
That’s it.
How to call onSubmit function from the onChange in Formik
You have to use such code
1 2 3 4 5 6 7 8 9 10 |
onChange={e => { e.persist(); setFieldValue('logInAndPublish', true, false) // the last argument prevents validation from running setFieldValue('publishAsGuest', false, false) // the last argument prevents validation from running window.logInAndPublish.checked = true window.publishAsGuest.checked = '' console.log('submitForm = ', submitForm); submitForm() }} |
use setFieldValue with the third argument false, because without it won’t work.
How to scroll page in react
Sometimes you show the form on the page and you want to put the user on the top of form. To do this you have to use a window.scrollTo() function. To scroll on the top use window.scrollTo(0, 0)
You can save the current position and then return to it
1 2 3 4 5 6 7 |
this.setState({ orderForm: true, scrollToRewarded: { pageXOffset: window.pageXOffset, pageYOffset: window.pageYOffset } }) |
Returning back
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
... const { pageXOffset, pageYOffset } = this.state.scrollToRewarded console.log('1pageXOffset = ', pageXOffset, ' 1pageYOffset = ', pageYOffset) setTimeout(function() { window.scrollTo(pageXOffset, pageYOffset) console.log('here we are'); }, 0) // window.scrollTo(pageXOffset, pageYOffset) return ( <div> <Header {...this.props} locale={locale} /> ... |
How to create redirect in react with react-router-dom
You can use a few methods. The best is to use a history object
1 |
this.props.history.push(url) |
Or you can use a variable and <Redirect to={} /> method something like that
1 2 3 4 5 |
if (this.state.redirectToOrder) { return ( <Redirect push={true} to={`/${locale}/orders/${this.state.insertId}/`} /> ) } |
this method will lead to errors
How to make anchor by hasktag to the needed element in react
we can create a function scrollToMessages
1 2 3 4 5 6 7 8 9 |
scrollToMessages = () => { const anchor = this.props.location.hash.replace('#', '') if (anchor === 'messages') { const domElement = ReactDOM.findDOMNode(this.refs['messages']); if (domElement) { domElement.scrollIntoView(); } } } |
than put the ref to the element where to scroll
1 |
<h2 ref="messages">Order discussion</h2> |
then call the function inside componentDidMount and componentDidUpdate or whatever even handler method you would like
1 2 3 4 5 6 7 |
componentDidMount() { this.scrollToMessages() } componentDidUpdate() { this.scrollToMessages() } |
the end