How to get the url to insert as a data with Redux Form? - url

I was able to get the url in the attachment field but for the redux form it was empty, how is possible to pass the value of the url to the redux form? Below is the code and the screenshot:
<div className="FileUpload">
<Dropzone
onDrop={this.onImageDrop.bind(this)}
multiple={false}
accept="image/*">
<div>Drop an image or click to select a file to upload.</div>
</Dropzone>
</div>
<div className="form-group">
<label htmlFor="attachment">Attachment:</label><br />
<input className="form-control" focus placeholder="attachment" type="text" name="attachment" ref="attachment" value={this.state.uploadedFileCloudinaryUrl} />
{this.state.uploadedFileCloudinaryUrl === '' ? null :
<div>
<p>{this.state.uploadedFile.name}</p>
<img src={this.state.uploadedFileCloudinaryUrl} alt="" />
</div>}
</div>
<div className="ui small image">
<img src={this.props.workrequest.attachment} alt="" />
</div>
the url in the attachemnt field
The first one is using the React Dropzone to get the url but for the Redux Form it was empty. May I know how to do that to get the url inserts at Redux Form here? Thank you

import React from 'React';
import { connect } from 'react-redux';
import { change, reduxForm } from 'redux-form';
import Dropzone from 'react-dropzone';
class UploadForm extends React.Component {
onDrop = (accepted) => {
if (!accepted.length) return;
// start uploading
this.setState({ isUploading: true });
const formData = new FormData();
formData.append('file', accepted[0]);
axios.post('upload', formData).then(
(res) => {
this.props.dispatch(change('uploadForm', 'url', res.url));
this.setState({ isUploading: false });
},
() => {
this.setState({ isUploading: false });
}
);
};
render() {
return (
<form>
<Dropzone onDrop={this.onDrop} />
</form>
);
}
}
export default connect()(
reduxForm({
form: 'uploadForm',
initialValues: {
url: ''
}
})(UploadForm)
);
Please use this.

Actually, you must use Field component from Redux-form.
Other wise, you can change form values using dispatch and change action creator.
import { Field, change } from 'redux-form';
this.props.dispatch(change('uploadForm', 'url', this.state.url));

Related

TypeError: Cannot read property 'message' of undefined ---using react-hook-form

I am trying to display an error message when nothing is typed inside the message input form, but when I load the page I get this error 'TypeError: Cannot read property 'message' of undefined'. I am using react-hook-forms. This is my code down below.
import { Button } from "#material-ui/core";
import { Close } from "#material-ui/icons";
import React from "react";
import { useForm } from "react-hook-form";
import "./SendMail.css";
const SendMail = () => {
const { register, handleSubmit, watch, errors } = useForm();
const onSubmit = (formData) =>{
console.log(formData)
}
return (
<div className="sendMail">
<div className="sendMail__header">
<h3>New Message</h3>
<Close className="sendMail__close" />
</div>
<form onSubmit={handleSubmit(onSubmit)}>
<input name='to' placeholder="To" type="text" {...register('to',{required:true})}/>
<input name="subject" placeholder="Subject" type="text" {...register('subject',{required:true})} />
<input
name="message"
placeholder="Message..."
type="text"
className="sendMail__message"
{...register('message',{required:true})}
/>
{errors.message && <p>To is required!!</p>}
<div className="sendMail__send">
<Button
className="sendMail__send"
variant="contained"
color="primary"
type="submit"
>
Send
</Button>
</div>
</form>
</div>
);
};
export default SendMail;
Since v7 the errors object moved to the formState property, so you need to adjust your destructering:
const { register, handleSubmit, watch, formState: { errors } } = useForm();

svelte keep updating store var without clicking to update

My app automatically update $content value without me clicking on buttons. I know it is a simple question, but I can't find out why, I'm learning svelte.
App.svelte
<script>
import { content } from './store.js';
import Item from './Item.svelte';
$content = [{ id:0,obj: "Fell free to browse any category on top." }];
function addContent(value) {
$content = [{ id:0,obj: value}]
}
</script>
<li><button on:click={addContent("Home Page")}>Home</button></li>
<li><button on:click={addContent("Products Page")}>Products</button></li>
<div class="Content">
<p>Fell free to browse any category on top.</p>
{#each $content as item}
<p><svelte:component this={Item} objAttributes={item} /></p>
{/each}
</div>
store.js
import { writable } from 'svelte/store';
export let content = writable({});
Item.svelte
<script>
import { fade } from 'svelte/transition';
export let objAttributes = {};
</script>
<p transition:fade>
{objAttributes.obj}
{#if objAttributes.otherattrib}<em>{objAttributes.otherattrib}</em>{/if}
</p>
This is because your on:click events are defined wrongly.
The on:click takes as argument a function like this
<button on:click={functionGoesHere}>
or, if you want it inlined
<button on:click={() => { }>
What happens in your case is that you directly call a function and the result of this function will then be called when the button is clicked. You can see that in this example:
<script>
function createFn() {
return () => console.log('logging this')
}
</script>
<button on:click={createFn}>Click here</button>
in this example the function () => console.log('logging this') will be attached the button.
So to come back to your code, this is easily fixed by making it a function instead of a function call:
<li><button on:click={() => addContent("Home Page")}>Home</button></li>

Images not loading on page change using Link in NextJS

This is hard to explain without uploading my full project likely, but here goes. I think I've narrowed it down to some combination of getInitialProps() and getStaticProps(). When I use next/link to change pages images are not being loaded. If I browse directly to the page images will load fine. Project is fairly simple with only 2 pages, index.js and [slug].js. Here's both:
index.js
import React from 'react';
import Layout from '../components/layout';
import Seo from '../components/seo';
import Hero from '../components/hero';
import Forcast from '../components/forcast';
import { fetchAPI } from '../lib/api';
import ReactMarkdown from 'react-markdown';
const Home = ({ pages, homepage }) => {
return (
<Layout pages={pages}>
<Seo seo={homepage.seo} />
<Hero hero={homepage.hero} />
<Forcast />
<main className='main-content'>
<div className='fullwidth-block'>
<div className='container'>
<div className='post single'>
<div className='entry-content'>
<ReactMarkdown
source={homepage.Content}
escapeHtml={false}
transformImageUri={uri =>
uri.startsWith('http') ? uri : `${process.env.REACT_APP_IMAGE_BASE_URL}/${uri}`
}
/>
</div>
</div>
</div>
</div>
</main>
</Layout>
);
};
export async function getStaticProps() {
// Run API calls in parallel
const [pages, homepage] = await Promise.all([
fetchAPI('/pages'),
fetchAPI('/homepage'),
]);
return {
props: { pages, homepage },
revalidate: 1,
};
}
export default Home;
[slug].js
import ReactMarkdown from 'react-markdown';
import Layout from '../components/layout';
import Seo from '../components/seo';
import { fetchAPI } from '../lib/api';
const Page = ({ page, pages }) => {
const seo = {
metaTitle: page.Title,
metaDescription: page.seo.metaDescription,
shareImage: page.seo.shareImage,
}
return (
<Layout pages={pages}>
<Seo seo={page.seo} />
<main className='main-content'>
<div className='container'>
<div className='breadcrumb'>
</div>
</div>
<div className='fullwidth-block'>
<div className='container'>
<div className='row'>
<div className='content col-md-8'>
<div className='post single'>
<h2 className='entry-title'>{page.Title}</h2>
<ReactMarkdown
source={page.Content}
escapeHtml={false}
transformImageUri={uri =>
uri.startsWith('http') ? uri : `${process.env.REACT_APP_IMAGE_BASE_URL}${uri}`
}
/>
</div>
</div>
</div>
</div>
</div>
</main>
</Layout>
);
};
export async function getStaticPaths() {
const pages = await fetchAPI('/pages');
return {
paths: pages.map((page) => ({
params: {
slug: page.slug,
},
})),
fallback: false,
};
}
export async function getStaticProps({ params }) {
const pages = await fetchAPI(
`/pages?slug=${params.slug}`
);
return {
props: { page: pages[0], pages },
revalidate: 1,
};
}
export default Page;
This might also be a Strapi issue though I'm not sure.
The issue happens because the REACT_APP_IMAGE_BASE_URL is not exposed to the browser, and only available on the server.
To have it exposed to the browser you'll need to add the NEXT_PUBLIC_ prefix to it.
# .env.development
NEXT_PUBLIC_REACT_APP_IMAGE_BASE_URL=http://localhost:1337
Then in your code reference it using process.env.NEXT_PUBLIC_REACT_APP_IMAGE_BASE_URL.

How to register 'react-bootstrap-typeahead' component using React 'useForm' hook?

I'm building a simple html form using "react-hook-form" library: https://react-hook-form.com/
I've incorporated "react-bootstrap-typeahead" into the html form but haven't been able to register this component with 'useForm' hook. Hence, "react-bootstrap-typeahead" input data is ignored during onSubmit.
"react-bootstrap-typeahead" doesn't provide a "name" prop which makes it difficult to register the component.
I've read the 'useForm' documentation on the different options for registering this type of components but still don't understand how to achieve this: https://react-hook-form.com/get-started#Registerfields
Does anybody have faced such challenge before?
It would be great to see a working example to get a better idea on how to implement "react-bootstrap-typeahead" + "react-hook-form" in my application. Thanks!
Here's my sample code:
import useForm from 'react-hook-form';
import { Typeahead } from 'react-bootstrap-typeahead';
import 'react-bootstrap-typeahead/css/Typeahead.css';
const myForm = (props) => {
const { register, handleSubmit, errors } = useForm();
const onSubmit = data => {
// api post request with form data
})
};
const mydata = [ "one", "two", "three" ];
return (
<>
<form onSubmit={handleSubmit(onSubmit)} >
<div className="form-group">
{/* Here I'm registering text input using ref: */}
<input type="text" className="form-control" name="name" ref={register({ required: true })} />
</div>
<div className="form-group mb-0">
{/* How can I register the below component with useForm? */}
<Typeahead
id="multiple-typeahead"
clearButton
multiple
options={mydata}
/>
</div>
<button type="submit">Save</button>
</form>
</>
);
}
This is how i was able to register the component:
import useForm from 'react-hook-form';
import { useForm, Controller } from "react-hook-form";
import 'react-bootstrap-typeahead/css/Typeahead.css';
const myForm = (props) => {
const { register, handleSubmit, errors, control } = useForm();
const onSubmit = data => {
// api post request with form data
})
};
const mydata = [ "one", "two", "three" ];
return (
<>
<form onSubmit={handleSubmit(onSubmit)} >
<div className="form-group">
<input type="text" className="form-control" name="name" ref={register({ required: true })} />
</div>
<div className="form-group mb-0">
<Controller
as={Typeahead}
control={control}
name="typeahead_component"
rules={{ required: true }}
id="multiple-typeahead"
clearButton
multiple
options={mydata}
defaultValue=""
/>
</div>
<button type="submit">Save</button>
</form>
</>
);
}

React Axios to Rails Knock

I am trying to send a POST request from axios to a Rails API using the following function in the React frontend:
export function registerUser({ name, email, password }) {
var postdata = JSON.stringify({
auth: {
name, email, password
}
});
return function(dispatch) {
axios.post(`${API_URL}/user_token`, postdata )
.then(response => {
cookie.save('token', response.data.token, { path: '/' });
dispatch({ type: AUTH_USER });
window.location.href = CLIENT_ROOT_URL + '/dashboard';
})
.catch((error) => {
errorHandler(dispatch, error.response, AUTH_ERROR)
});
}
}
The Knock gem expects the request in the following format:
{"auth": {"email": "foo#bar.com", "password": "secret"}}
My current function seem to generate the correct format (inspecting the request in the browser devtools), but I'm getting the following error:
Uncaught (in promise) Error: Objects are not valid as a React child
(found: object with keys {data, status, statusText, headers, config,
request}). If you meant to render a collection of children, use an
array instead or wrap the object using createFragment(object) from the
React add-ons. Check the render method of Register.
class Register extends Component {
handleFormSubmit(formProps) {
this.props.registerUser(formProps);
}
renderAlert() {
if(this.props.errorMessage) {
return (
<div>
<span><strong>Error!</strong> {this.props.errorMessage}</span>
</div>
);
}
}
render() {
const { handleSubmit } = this.props;
return (
<form onSubmit={handleSubmit(this.handleFormSubmit.bind(this))}>
{this.renderAlert()}
<div className="row">
<div className="col-md-6">
<label>Name</label>
<Field name="name" className="form-control" component={renderField} type="text" />
</div>
</div>
<div className="row">
<div className="col-md-12">
<label>Email</label>
<Field name="email" className="form-control" component={renderField} type="text" />
</div>
</div>
<div className="row">
<div className="col-md-12">
<label>Password</label>
<Field name="password" className="form-control" component={renderField} type="password" />
</div>
</div>
<button type="submit" className="btn btn-primary">Register</button>
</form>
);
}
}
The error is caused by the following line in your code
errorHandler(dispatch, error.response, AUTH_ERROR)
The exception raised clearly explains that. Instead of setting error.response, try to use the actual data from error.response. E.g error.response.data. Also, you can try replacing the error.response with a string and see how that behaves, then reference the string you need from error.response.data.

Resources