SingleDatePicker by react-dates is not closing on change - reactjs

Hey I have set up a react dates functionality on my app, however the date, when chosen doesnt make the calendar close.
I have the example here on https://codesandbox.io/s/magical-dubinsky-xuxkj?file=/src/App.js:0-681
import React, { useState } from "react";
import { SingleDatePicker } from "react-dates";
import "react-dates/initialize";
import "react-dates/lib/css/_datepicker.css";
const CreateGroupEvent = (props) => {
const [dob, setDob] = useState(null);
const [focused, setFocused] = useState(false);
const setDate = (date) => {
setDob(date);
setFocused(false);
};
return (
<>
<SingleDatePicker
date={dob}
// {...input}
onOutsideClick={true}
numberOfMonths={1}
onDateChange={setDate}
focused={focused}
onFocusChange={setFocused}
id="dob"
/>
</>
);
};
export default CreateGroupEvent;

** EDITED : Here is my example code sandbox.
How about trying this?
According to its document, onFocusChange seems to should take { focused : boolean } objects as parameters.
const onFocusChange = ({ focused }) => {
setFocused(focused);
};
<SingleDatePicker
date={dob}
onOutsideClick={true}
numberOfMonths={1}
onDateChange={setDate}
focused={focused}
onFocusChange={onFocusChange}
id="dob"
/>

This seems to be a version related quirk -- if you just do:
onFocusChange={(focusedInput)=> setFocused(focusedInput.focus)}
it'll work.

Related

How to get a value from code mirror in react js?

I am trying to get a value from the code mirror input field but I don't know why I am not getting the value from code mirror input field
import CodeMirror from "#uiw/react-codemirror";
import { markdown, markdownLanguage } from "#codemirror/lang-markdown";
import { languages } from "#codemirror/language-data";
export default function Editor() {
const [get, set] = useState("");
console.log(get); {/* doesn't display anything */}
return (
<>
<CodeMirror
value={get}
extensions={[
markdown({ base: markdownLanguage, codeLanguages: languages }),
]}
onInput={(e) => set(e.target.value)}
/>
</>
);
}
Try useEffect hook, it calls the function inside whenever variable in second argument array changes, in this specific scenario when get changes.
import CodeMirror from "#uiw/react-codemirror";
import { markdown, markdownLanguage } from "#codemirror/lang-markdown";
import { languages } from "#codemirror/language-data";
import { useEffect } from "react";
export default function Editor() {
const [get, set] = useState("");
useEffect(() => {
console.log(get) //gets called whenever get state changes
}, [get])
return (
<>
<CodeMirror
value={get}
extensions={[
markdown({ base: markdownLanguage, codeLanguages: languages }),
]}
onInput={(e) => set(e.target.value)}
/>
</>
);
}
The onChange handler can output the value as below.
import { markdown, markdownLanguage } from "#codemirror/lang-markdown";
import { languages } from "#codemirror/language-data";
import { useState } from "react";
export default function Editor() {
const [get, set] = useState("");
console.log(get);
return (
<>
<CodeMirror
value={get}
extensions={[
markdown({ base: markdownLanguage, codeLanguages: languages })
]}
onChange={(value) => set(value)}
/>
</>
);
}
Working example

How to stop rendering every keystroke input field onChange in React

Is there a better way to stop rendering every keystroke input field onChange in React... I noted that if I changed the value to onBlur() on input field, however it doesn't dispatch AddReservation function the second part to clear the input field (setReservationCardInput('')).
Or I cannot stop rendering onChange due to setReservationCardInput update reservationCardInput with useState() function?
My application is below, appreciate your feedback, thank you!
import React, {useState} from 'react'
import {useSelector, useDispatch} from 'react-redux'
import ReservationCard from '../../components/ReservationCard'
import {addReservation} from '../reservation/reservationsSlice'
const ReservationsList = () => {
const reservations = useSelector(state => state.reservations.value)
const [reservationCardInput, setReservationCardInput] = useState('')
const dispatch = useDispatch()
const inputOnChange = (e) => {
setReservationCardInput(e.target.value)
}
console.log('reservations:', reservationCardInput)
const AddReservation =() => {
if(!reservationCardInput) return
dispatch(addReservation(reservationCardInput))
setReservationCardInput('')
}
return (
<div className="reservation-cards-container">
{
reservations.map((name, index) => {
return (
<ReservationCard name={name} key={index}/>
)
})
}
<div className="reservation-input-container">
<input value={reservationCardInput} onChange={inputOnChange}/>
<button onClick={AddReservation}>Add Customer</button>
</div>
</div>
)
}
export default ReservationsList

Cannot close an antd modal using reactJS library

I need your helps, when I do click those 3 buttons on the red circles, It threw an error that's called '... is not a function' though I think closing a modal needs an useState hook which set boolean to close it. Am I wrong? If I'm not wrong so how to solve it, please help me!~~~
Images show error 1
Images show error 2
Here is my code
import {createContext, useState, useContext, useMemo} from 'react'
import { AuthContext } from './AuthProvider'
import useFirestore from '../hooks/useFirestore'
export const AppContext = createContext()
function AppProvider ({children}) {
const [isAddRoomVisible, setIsAddRoomVisible] = useState(false)
const user = useContext(AuthContext)
const {uid} = user
const roomsCondition = useMemo(() => {
return {
fieldName: 'members',
operator: 'array-contains',
value: uid
}
}, [uid])
const rooms = useFirestore('rooms', roomsCondition)
return (
<AppContext.Provider value={[rooms, isAddRoomVisible, setIsAddRoomVisible]}>
{children}
</AppContext.Provider>
)
}
export default AppProvider
import {Modal, Form, Input} from 'antd'
import { useState, useContext } from 'react'
import { AppContext } from '../../Context/AppProvider'
import { AuthContext } from '../../Context/AuthProvider'
import { addDocument } from '../../firebase/service'
export default function AddRoomModal() {
const [isAddRoomVisible, setIsAddRoomVisible] = useContext(AppContext)
const user = useContext(AuthContext)
const {uid} = user;
const [form] = Form.useForm()
const handleOk = () => {
// console.log({
// formData: form.getFieldsValue()
// })
addDocument('rooms', {...form.getFieldsValue(), members: [uid]})
setIsAddRoomVisible(false)
}
const handleCancel = () => {
setIsAddRoomVisible(false)
}
return (
<div>
<Modal
title="Create room"
visible={isAddRoomVisible}
onOk={handleOk}
okCancel={handleCancel}
>
<Form form={form} layout="vertical">
<Form.Item label="Room's name" name="name">
<Input placeholder="Enter room's name here"/>
</Form.Item>
<Form.Item label="Description" name="description">
<Input.TextArea placeholder="Enter description"/>
</Form.Item>
</Form>
</Modal>
</div>
)
}
shouldn't the first row of AddRoomModal be :
const [room, isAddRoomVisible, setIsAddRoomVisible] = useContext(AppContext)
You are destructuring an array not an object, so you cannot skip any element of the value prop of your context
EDIT :
Ok so i'll try to give you more info.
The first thing I notice is you are using a difficult way to handle your modal using a context. it would be easier to include your component in another that will contain the opening button and the modal open state :
const ModalParent = () => {
const [isModalOpen, setIsModalOpen] = useState(false);
return (
<>
<button onClick={() => setIsModalOpen(true)}>openModal</button>
<Modal
title="Create room"
visible={isModalOpen}
onOk={(e) => {
setIsModalOpen(false);
}}
okCancel={(e) => {
setIsModalOpen(false);
}}
>
Hi my Modal !
</Modal>
</>
);
};
But you can still use the context approach, it allows you to control your modal from anywhere in your app, which can be pretty useful.
When you are using your context provider, you are passing it an array containing three values :
<AppContext.Provider value={[rooms, isAddRoomVisible, setIsAddRoomVisible]}>
When you are using the useContext hook, you are retrieving this array in your component.
const myAppContextValues = useContext(AppContext)
const rooms = myAppContextValues[0]
const isAddRoomVisible = myAppContextValues[1]
const setIsAddRoomVisible= myAppContextValues[2]
In you're case, you are using a syntax to define more quickly variables from an array called destructuring https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment .
But you are skipping an element of the array.
So if we translate your code in vanilla JS you are actually doing :
// Here you are retrieving the element 0 & 1 and putting them in variable isAddRoomVisible, setIsAddRoomVisible
// const [isAddRoomVisible, setIsAddRoomVisible] = useContext(AppContext)
// Under is the vanilla JS example
const myAppContextValues = useContext(AppContext)
const isAddRoomVisible = myAppContextValues[0]
const setIsAddRoomVisible= myAppContextValues[1]
So what you need to do is to also assign the room element, even if you don't use it
const [room, isAddRoomVisible, setIsAddRoomVisible] = useContext(AppContext)
You could also use an object as value of your context and destructuring it with the object syntax :
// notice that here i'm using the shorthand syntax to create an object https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#new_notations_in_ecmascript_2015
<AppContext.Provider value={{rooms, isAddRoomVisible, setIsAddRoomVisible}}>
// and here i'm using the object destructuring
const {isAddRoomVisible, setIsAddRoomVisible} = useContext(AppContext)
Hope it helps you and it is clearer !

onClickHandler sometimes work, sometimes not - React

The onClickHandler in the following code, in this component, 'SearchResult', sometimes work and sometimes not.
I can't figure out any logic that can explain why it works when it works, and why it's not working, when it's not working.
I've put a debugger inside the onClickHandler, at the beginning of it, and when it's not working, it doesn't get to the debugger at all - what indicates that the function sometimes isn't even called, and I can't figure out why.
Furthermore, I've tried to move all the code in function to the onClick, inline, but then, it's not working at all.
In addition, I've tried to use a function declaration instead of an arrow function, and it still behaves the same - sometimes it works, and sometimes it's not...
This is the site, you can see the behavior for yourself, in the search box.
This is the GitHub repository
Here you can see a video demonstrating how it's not working, except for one time it did work
Please help.
The problematic component:
import { useDispatch } from 'react-redux'
import { Col } from 'react-bootstrap'
import { getWeatherRequest } from '../redux/weather/weatherActions'
import { GENERAL_RESET } from '../redux/general/generalConstants'
const SearchResult = ({ Key, LocalizedName, setText }) => {
const dispatch = useDispatch()
const onClickHandler = () => {
dispatch({ type: GENERAL_RESET })
dispatch(
getWeatherRequest({
location: Key,
cityName: LocalizedName,
})
)
setText('')
}
return (
<Col className='suggestion' onClick={onClickHandler}>
{LocalizedName}
</Col>
)
}
export default SearchResult
This is the parent component:
import React, { useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { Form } from 'react-bootstrap'
import { getAutoCompleteResultsRequest } from '../redux/autoComplete/autoCompleteActions'
import { AUTO_COMPLETE_RESET } from '../redux/autoComplete/autoCompleteConstants'
import SearchResult from './SearchResult'
const SearchBox = () => {
const [text, setText] = useState('')
const dispatch = useDispatch()
const autoComplete = useSelector((state) => state.autoComplete)
const { results } = autoComplete
const onChangeHandler = (e) => {
if (e.target.value === '') {
dispatch({ type: AUTO_COMPLETE_RESET })
setText('')
}
setText(e.target.value)
dispatch(getAutoCompleteResultsRequest(e.target.value))
}
const onBlurHandler = () => {
setTimeout(() => {
dispatch({ type: AUTO_COMPLETE_RESET })
setText('')
}, 100)
}
return (
<div className='search-box'>
<Form inline>
<div className='input-group search-md search-sm'>
<input
type='search'
name='q'
value={text}
onChange={onChangeHandler}
onBlur={onBlurHandler}
placeholder='Search Location...'
className='mr-sm-2 ml-sm-3 form-control'
/>
</div>
</Form>
<div className='search-results'>
{results &&
results.map((result) => {
return (
<SearchResult key={result.Key} {...result} setText={setText} />
)
})}
</div>
</div>
)
}
export default SearchBox
I played a bit with your code and it looks like a possible solution may be the following addition in the SearchResult.js:
const onClickHandler = (e) => {
e.preventDefault();
...
After some tests
Please remove the onBlurHandler. It seams to fire ahaed of the onClickHandler of the result.
Can you put console.log(e.target.value) inside the onChangeHandler,
press again search results and make sure that one of it doesn't working and show us the console.
In searchResult component print to the console LocalizedName as well

Using Draft js mention plugin with react hooks

I have been trying to get draft js mention plugin to work with react hooks but can't seem to figure what's wrong with the code. Appreciate any help on this.
import React, { useRef, useState, useEffect } from "react";
import { EditorState } from "draft-js";
import Editor from "draft-js-plugins-editor";
import createMentionPlugin, { defaultSuggestionsFilter } from "draft-js-mention-plugin";
import mentions from "./mentions";
export default function MentionEditor() {
const [editorState, setEditorState] = useState(EditorState.createEmpty());
const [suggestions, setSuggestions] = useState(mentions);
const editor = useRef(null);
useEffect(() => {
editor.current.focus();
}, [])
const mentionPlugin = createMentionPlugin();
const { MentionSuggestions } = mentionPlugin;
const plugins = [mentionPlugin];
const onSearchChange = ({ value }) => {
setSuggestions(defaultSuggestionsFilter(value, mentions))
};
return (
<div style={{ border: "1px solid gray" }}>
<Editor
editorState={editorState}
onChange={editorState => setEditorState(editorState)}
plugins={plugins}
ref={editor}
/>
<MentionSuggestions
onSearchChange={onSearchChange}
suggestions={suggestions}
/>
</div>
);
}
You need to move the draft-js plugin configuration outside the component arrow function. This is a pretty basic Draft-JS implementation using a functional component and hooks:
import React, { useState, useRef } from 'react'
import { EditorState } from 'draft-js'
import Editor from 'draft-js-plugins-editor'
import createMentionPlugin, { defaultSuggestionsFilter } from 'draft-js-mention-plugin'
import 'draft-js/dist/Draft.css'
import 'draft-js-mention-plugin/lib/plugin.css'
import mentions from "./mentions"
// Draft-JS-Mentions plugin configuration
const mentionPlugin = createMentionPlugin()
const { MentionSuggestions } = mentionPlugin
const plugins = [mentionPlugin]
const MyEditor= () => {
const [suggestions, setSuggestions] = useState(mentions)
// Draft-JS editor configuration
const [editorState, setEditorState] = useState(
() => EditorState.createEmpty(),
)
const editor = useRef(null)
// Check editor text for mentions
const onSearchChange = ({ value }) => {
setSuggestions(defaultSuggestionsFilter(value, mentions))
}
const onAddMention = () => {
}
// Focus on editor window
const focusEditor = () => {
editor.current.focus()
}
return (
<div onClick={() => focusEditor()}>
<Editor
ref={editor}
editorState={editorState}
plugins={plugins}
onChange={editorState => setEditorState(editorState)}
placeholder={'Type here...'}
/>
<MentionSuggestions
onSearchChange={onSearchChange}
suggestions={suggestions}
onAddMention={onAddMention}
/>
</div>
)
}
export default MyEditor
Just move these lines outside component and it will work:
const mentionPlugin = createMentionPlugin();
const { MentionSuggestions } = mentionPlugin;
const plugins = [mentionPlugin];
export default function MentionEditor() {
const [editorState, setEditorState] = useState(EditorState.createEmpty());
.. ... ...
}
!!!!!!!!!!!!!!!! PAY ATTENTION !!!!!!!!!!!!
The onSearchChange method will be triggered once the '#' character is typed, so in this case it will return just 5 items that fit the empty string...
To prevent this to be happened, just check that the value we want to search is not empty:
const onSearchChange = ({ value }) => {
if (value) {
setSuggestions(defaultSuggestionsFilter(value, mentions));
}
};

Resources