Error props.render - React hook form with react-datapickers - javascript

I have problem with React&NextJS and React hook form and react datapickers. I get an error message: Uncaught TypeError: props.render is not a function. I understand that following an update you have to put render prop in the Controller component but I can't manage to set it up with react-datapickers. Has anyone been there before?
PAGE
import React, { useState } from 'react';
import ReactDOM from 'react-dom';
import { useForm, Controller } from 'react-hook-form';
import ReactDatePicker from 'react-datepicker';
//Components
import ButtonsResult from '../components/ButtonsResult';
//Style
import 'react-datepicker/dist/react-datepicker.css';
let renderCount = 0;
export default function DataPickersExample(props) {
const { handleSubmit, control } = useForm({});
const [data, setData] = useState(null);
renderCount++;
return (
<form
onSubmit={handleSubmit((data) => setData(data))}
className='form'
>
<div className='container'>
<section>
<label>React Datepicker</label>
<Controller
as={ReactDatePicker}
control={control}
valueName='selected'
onChange={([selected]) => selected}
name='ReactDatepicker'
className='input'
placeholderText='Select date'
/>
</section>
<ButtonsResult {...{ data }} />
</div>
</form>
);
}
COMPONENTS BUTTON
import React from 'react';
function ButtonsResult({ data}) {
return (
<>
{data && (
<pre style={{ textAlign: 'left', color: 'white' }}>
{JSON.stringify(data, null, 2)}
</pre>
)}
<button className='button'>submit</button>
</>
);
}
export default ButtonsResult;````

Related

Objects are not valid as a React child. found: object with keys {background, color}

i am trying to setting up darkMode button, but i got this error ... Uncaught Error: Objects are not valid as a React child (found: object with keys {background, color}). If you meant to render a collection of children, use an array instead.
here is my data..................
my Contextjs component......
import { createContext, useReducer } from "react";
export const themeContext = createContext();
const initialState = {darkMode : true};
const themeReducer = (state, action) =>{
switch(action.type){
case'toggle':
return {darkMode : !state.darkMode};
default:
return state;
}
};
export const ThemeProvider = (props)=>{
const [state, dispatch] = useReducer (themeReducer, initialState);
return(
<themeContext.Provider value={{state, dispatch}}>
{props.children}
</themeContext.Provider>
);
};
my AppJs component.......
import Navbar from "./Components/Navbar/Navbar";
import "./App.css"
import { Intro } from "./Components/Intro/Intro";
import Services from "./Components/Services/Services";
import Experience from "./Components/Experience/Experience"
import Works from "./Components/Works/Works"
import Portfolio from "./Components/Portfolio/Portfolio"
import Testimonials from './Components/Testtimonials/Testimonials'
import Contact from "./Components/Contact/Contact"
import Footer from "./Components/Footer/Footer"
import {themeContext} from './Context'
import { useContext } from "react";
function App() {
const theme = useContext(themeContext);
const darkMode = theme.state.darkMode;
return (
<div className="App">
style={{
background : darkMode? 'black' : '',
color : darkMode? 'white' : ''
}}
<Navbar />
<Intro />
<Services />
<Experience />
<Works />
<Portfolio/>
<Testimonials/>
<Contact />
<Footer />
</div>
);
}
export default App;
and here is IndexJs..........
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import {ThemeProvider} from './Context';
ReactDOM.render(
<ThemeProvider>
<App />
</ThemeProvider>,
document.getElementById('root')
);
and error is:- Uncaught Error: Objects are not valid as a React child (found: object with keys {background, color}). If you meant to render a collection of children, use an array instead.
You have to pass style prop to component.
<div
className="App"
style={{
background: darkMode ? "black" : "",
color: darkMode ? "white" : "",
}}
>
I would rather prefer, create 2 classes dark and light and use like this:
<div className={`App ${darkMode ? "dark" : "light"}`}>
It's trying to render your style object as a child of the div, update it so it is an attribute of the div.
<div
className="App"
style={{
background: darkMode ? "black" : "",
color: darkMode ? "white" : "",
}}
>
<Navbar />
<Intro />
<Services />
<Experience />
<Works />
<Portfolio />
<Testimonials />
<Contact />
<Footer />
</div>

Object is undefined when trying to fetch it using useContext()

I am very new to React and was trying to make a context in React so that in my notes app such that I can trigger my custom made alert for relevant user activity but when I am trying to use the values from the context using useContext I am getting error : "Cannot destructure property 'alert' of 'Object(...)(...)' as it is undefined."
Here's the code:-
Creating Context
import React from 'react';
const AlertContext = React.createContext(null);
export default AlertContext;
Populating Value to the Context
import React,{useState} from 'react';
import AlertContext from "./AlertContext";
const ShowAlert = (props)=>{
const [alert,setAlert] = useState(null);
const showAlert = (message,type)=>{
setAlert({
msg:message,
type:type
})
setTimeout(()=>{
setAlert(null);
},3000);
}
return(
<AlertContext.Provider value={{alert,showAlert}}>
{props.children}
</AlertContext.Provider>
)
}
export default ShowAlert;
Trying to use the values
import React, { useContext } from "react";
import { Navbar, Button, Nav } from "react-bootstrap";
import { Link, useHistory } from "react-router-dom";
import ShowAlert from "../contexts/ShowAlert";
import MyAlert from "./MyAlert";
function Header() {
const {alert} = useContext(ShowAlert);
let history = useHistory();
const handleLogout = () => {
localStorage.removeItem("token");
history.push("/login");
};
return (
<>
<header>
<Navbar collapseOnSelect expand="lg" className="header">
<Navbar.Brand className="heading">
<Link to="/" className="headerLink">
Note Cloud
</Link>
<i className="fas fa-cloud-upload-alt cloudIcon"></i>
</Navbar.Brand>
<Navbar.Toggle aria-controls="responsive-navbar-nav" />
<Navbar.Collapse id="responsive-navbar-nav">
<Nav className="me-auto"></Nav>
{localStorage.getItem("token") && (
<Nav>
<Nav.Link>
<Button variant="primary" size="lg" onClick={handleLogout}>
Logout
</Button>
</Nav.Link>
</Nav>
)}
</Navbar.Collapse>
</Navbar>
</header>
<MyAlert alert={alert}></MyAlert>
</>
);
}
export default Header;
Edit:- MyAlert Component
import React, { useContext } from "react";
import { Alert } from "react-bootstrap";
import ShowAlert from "../contexts/ShowAlert";
const MyAlert = (props) => {
const {alert} = useContext(ShowAlert);
const capitalize = (word) => {
if(word==="danger")
{
word = "error";
}
const lower = word.toLowerCase();
return lower.charAt(0).toUpperCase() + lower.slice(1);
};
return (
<div style={{ height: "50px" , width:"100%"}}>
{alert && (
<Alert
variant={alert.type}
>
<Alert.Heading>{capitalize(alert.type)}</Alert.Heading>
<p>{capitalize(alert.msg)}</p>
</Alert>
)}
</div>
);
};
export default MyAlert;
Error That I am getting
Try doing the Context like this instead of null.
import React from "react";
const AlertContext = React.createContext({
alert: {},
setAlert: (alert) => {},
});
export default
i think your export is the fail
export const AlertContext = React.createContext({})
or as well you can try:
< AlertContext.Consumer>
{(context) => {
console.log(context)
}}
</AlertContext.Consumer>

Navbar not updating after state change

As the title says my navbar is not changing the fragments after updating the state. I have no idea how to refresh it and other ideas seems to not work for me. I have tried to change the statements.
All i want to do is, after a user logs in successfully the state changes to true and the navbar updates with the corrent components. Thank you !
Home.js
import React, { useEffect } from 'react'
function Home() {
useEffect(()=>{
if(!localStorage.getItem("loggedIn")){
localStorage.setItem("loggedIn",false);
}
},[]);
return (
<div>
Home
</div>
)
}
export default Home
Login.js
import React from 'react';
import './Login.css';
import Axios from 'axios';
import { useEffect, useState } from "react";
import {useHistory} from 'react-router-dom';
function Login() {
const[username,setUsername] = useState('');
const[password,setPassword] = useState('');
const[errorMessage,setErrorMessage] = useState('');
let history = useHistory();
const login = () =>{
console.log(username);
Axios.post("http://localhost:3001/user/login",{username: username,password: password}).then((response) => {
//console.log(response);
if(response.data.loggedIn){
localStorage.setItem("loggedIn",true);
localStorage.setItem("username",response.data.username);
history.push('/');
}else{
setErrorMessage(response.data.message);
}
});
};
return (
<div className="Login">
<h1>Login to your BugTrack account !</h1>
<div className="LoginForm">
<input type="text" placeholder="USERNAME"
onChange={(event)=>{setUsername(event.target.value)}}/>
<input type="password" placeholder="PASSWORD"
onChange={(event)=>{setPassword(event.target.value)}}/>
<button onClick={login}>Login to you account</button>
<h1 style={{color: "red"}}>{errorMessage}</h1>
</div>
</div>
);
}
export default Login
Navbar.js
import React, { useEffect, useState, Component, Fragment } from 'react';
import './Navbar.css';
function Navbar() {
const [loggedIn, setLoggedIn] = useState(false);
useEffect(()=> {
setLoggedIn(localStorage.getItem("loggedIn"));
},[localStorage.getItem("loggedIn")]);
return (
<div className="Navbar">
Home
{!loggedIn ? (
<Fragment>
Profile
</Fragment>
):(
<Fragment>
Register
Login
</Fragment>
)}
</div>
);
}
export default Navbar;
You want to to use localStorage as a useEffect dependency which isn't supports for React to rerender/update the component. Check this: useEffect do not listen for localStorage - it's like duplicate of your question.

Why does "Element type is invalid: expected a string" in this simple example?

I was in the process of doing a Sandbox for another question but have encountered this issue which is driving me nuts. It's a simple example but I can't understand why it won't render and I get
I have a case where I want to switch between two views which in my real code are two complex components.
App.js
import React, { useState, useMemo } from "react";
import "./styles.css";
import DisplayComponent1 from "./DisplayComponent1";
import DisplayComponent2 from "./DisplayComponent2";
import Button from "#material-ui/core";
export default function App() {
const numbersToDisplay = [1, 2, 3];
////////////////////////////////////////////////
const component1 = useMemo(() => {
return (
<DisplayComponent1
style={{ border: "1px solid blue" }}
numbers={numbersToDisplay}
/>
);
}, [numbersToDisplay]);
const component2 = useMemo(() => {
return (
<DisplayComponent2
style={{ border: "1px solid red" }}
numbers={numbersToDisplay}
/>
);
}, [numbersToDisplay]);
////////////////////////////////////////////////
const [currentDisplayComponent, setCurrentDisplayComponent] = useState(
component1
);
return (
<div className="App">
<Button
variant="contained"
onClick={() => setCurrentDisplayComponent(component1)}
>
Show Display 1
</Button>
<Button
variant="contained"
onClick={() => setCurrentDisplayComponent(component2)}
>
Show Display 2
</Button>
{currentDisplayComponent}
</div>
);
}
DisplayComponent1.js & DisplayComponent2.js
import React from "react";
import Paper from "#material-ui/core";
export default function DisplayComponent1(props) {
return (
<Paper>
<p>This is DisplayComponent1</p>
</Paper>
);
}
import React from "react";
import Paper from "#material-ui/core";
export default function DisplayComponent2(props) {
return (
<Paper>
<p>This is DisplayComponent2</p>
</Paper>
);
}
Your imports from material-ui are incorrect.
You need to import Paper and Button as named imports
import {Paper} from "#material-ui/core"; // In DisplayComponent1 and DisplayComponent2
and
import {Button} from "#material-ui/core"; // In App.js
Working demo

react-pdf - Error: Target container is not a DOM element

I am using React with react-pdf and trying to render a PDF into my modal. However, my modal gets loaded on a button click, so it's not loaded on app load. But it is trying to call the PDF rendering call on app load and thus generating the error: 'Error: Target container is not a DOM element'. I'm not sure of how to fix this issue.
Here is my entire modal component:
import ReactModal from 'react-modal';
import React, { useEffect, useRef } from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import ReactPDF, { PDFViewer } from '#react-pdf/renderer';
import CloseButton from './CloseButton';
import MessageHub from '../message/MessageHub';
import PDFPlacard from '../placards/PDFPlacard';
const PDF = () => (
<PDFViewer>
<PDFPlacard />
</PDFViewer>
);
const PlacardsModal = (props) => {
const { openPlacards, setOpenPlacards, customStyles } = props;
const numPlacards = React.createRef();
const ref = useRef(null);
// this call needs to happen after the modal and #PDFPlacard is rendered
ReactDOM.render(<PDF />, document.getElementById('PDFPlacard'));
const handleSubmit = (evt) => {
evt.preventDefault();
if (numPlacards.current.value === '') {
ref.current('Please fill in the number of placards.');
} else {
// submit form
}
};
return (
<ReactModal
isOpen={openPlacards}
style={customStyles}
className={'print-placards-modal'}
closeTimeoutMS={1000}
>
<CloseButton setOpenModal={setOpenPlacards} />
<h2>Print Placards</h2>
{/* eslint-disable-next-line react/no-children-prop */}
<MessageHub children={(add) => (ref.current = add)} />
<form className={'form'} onSubmit={handleSubmit}>
<div className={'form-group row'}>
<label
htmlFor={'numPlacards'}
className={'col-sm-6 col-form-label'}
>
Number of Placards:
</label>
<div className={'col-sm-6'}>
<input
id={'numPlacards'}
type={'number'}
className={'form-control'}
ref={numPlacards}
/>
</div>
</div>
<button
className={'btn btn-primary d-block mx-auto mb-2'}
type={'submit'}
value={'Print'}
/>
</form>
<div id={'PDFPlacard'} />
</ReactModal>
);
};
PlacardsModal.propTypes = {
openPlacards: PropTypes.bool,
setOpenPlacards: PropTypes.func,
customStyles: PropTypes.object,
title: PropTypes.string
};
export default PlacardsModal;
Here is PDFPlacard.js:
import React from 'react';
import {
Page,
Text,
View,
Document,
StyleSheet
} from '#react-pdf/renderer';
// Create styles
const styles = StyleSheet.create({
page: {
flexDirection: 'row',
backgroundColor: '#E4E4E4'
},
section: {
margin: 10,
padding: 10,
flexGrow: 1
}
});
// Create Document Component
const PDFPlacard = (type) => (
<Document>
<Page size="letter" style={styles.page}>
<View style={styles.section}>
<Text>Section #1</Text>
</View>
<View style={styles.section}>
<Text>Section #2</Text>
</View>
</Page>
</Document>
);
export default PDFPlacard;
And my index.js:
import React from 'react';
import { render } from 'react-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap/dist/js/bootstrap.min';
import './index.css';
import App from './App';
const title = 'title';
render(<App title={title} />, document.getElementById('root'));
// eslint-disable-next-line no-undef
module.hot.accept();
The parent is loading the PlacardsModal like this:
...
<button
className={'btn btn-info mb-3'}
onClick={() => setOpenPlacards(true)}
>
Placards
</button>
...
<PlacardsModal
openPlacards={openPlacards}
setOpenPlacards={setOpenPlacards}
customStyles={customStyles}
/>
Finally got the answer from another source. I should not have been making that ReactDOM.render( call at all. I should just have been including the PDF components on my page.
Like this:
...
<button
className={'btn btn-primary d-block mx-auto mb-2'}
type={'submit'}
value={'Print'}
/>
</form>
<!-- not this -->
<div id={'PDFPlacard'} />
<!-- this -->
<PDF />
</ReactModal>
);
};
...

Categories

Resources