value on autocomplete not changing when state updated - react-hooks

Im having difficulties on changing the autocomplete value, every time I click swap button.
I have application with 2 autocomplete, from and to. After click the swap button, Inside the swap function I will toggle the state from and to
The toggle of the state works but the value in autocomplete input not change. How can I achieved this? Thank you
below is the code and as well codeSandbox https://codesandbox.io/s/combobox-material-demo-forked-yup8d?file=/demo.js
export default function ComboBox() {
const [from, setFrom] = useState({});
const [to, setTo] = useState({});
const onChangeTo = (e, value) => {
setTo(value);
};
const onChangeFrom = (e, value) => {
setFrom(value);
};
const swap = () => {
setFrom(to);
setTo(from);
};
return (
<>
<Autocomplete
disablePortal
id="combo-box-demo"
options={top100Films}
value={from.label}
sx={{ width: 300 }}
onChange={(e, value) => onChangeFrom(e, value)}
renderInput={(params) => <TextField {...params} label="Movie" />}
/>
<Autocomplete
disablePortal
id="combo-box-demo"
options={top100Films}
value={to.label}
sx={{ width: 300 }}
onChange={(e, value) => onChangeTo(e, value)}
renderInput={(params) => <TextField {...params} label="Movie" />}
/>
<Button variant="outlined" onClick={() => swap()}>
SWAP
</Button>
</>
);
}

You can provide valid, defined initial state so the inputs remain as controlled inputs.
const [from, setFrom] = useState({ label: '' });
const [to, setTo] = useState({ label: '' });

Related

Formik does not update value from input

I am trying to add Form to my application, so I decided to pick formik and I ran into a little problem
I have following components:
After typing something in input, I am clicking submit and alert appears with empty data like:
{
someName: ''
}
Why someName does not update?
const SearchInput = ({name, ...props}) => {
const [field] = useField(name);
return (
<Styled.Wrapper>
<Styled.Input {...field} {...props} placeholder="Search" />
</Styled.Wrapper>
);
};
const Form = () => {
return (
<Formik
initialValues={{
someName: '',
}}
onSubmit={(values, actions) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
actions.setSubmitting(false);
}, 1000);
}}
>
{(props: FormikProps<Values>) => (
<FormikForm>
<SearchInput
name="someName"
type="text"
label="Some Name"
onChange={props.handleChange}
value={props.values.jobName}
/>
<button type="submit">Submit</button>
</FormikForm>
)}
</Formik>
)
};
export default Form;

Upload image one at a time with preview issue - React Drop zone

const [files, setFiles] = useState([]);
const onDrop = useCallback((acceptedFiles) => {
// Do something with the files
setFiles(
acceptedFiles.map((file: File) =>
Object.assign(file, {
preview: URL.createObjectURL(file),
})
)
);
}, []);
const { getRootProps, getInputProps } = useDropzone({
onDrop,
accept: 'image/*',
multiple: false,
});
const thumbs = files.map((file: { [key: string]: string }) => (
<div className={classes.imagePreview} key={file.name}>
<img className={classes.image} src={file.preview} alt={file.name} />
</div>
));
useEffect(() => {
// Make sure to revoke the data uris to avoid memory leaks
files.forEach((file: { [key: string]: string }) =>
URL.revokeObjectURL(file.preview)
);
}, [files]);
My HTML
<div className={classes.imageContainer}>
{thumbs}
<div className={classes.borderBox} {...getRootProps()}>
<input {...getInputProps()} />
<div>
<AddIcon />
</div>
</div>
</div>
I am trying to upload via dropzone one at a time however my image gets replaced with the second one.
Fixed it with appending to the state
const onDrop = useCallback(
(acceptedFiles) => {
// Process files
const oneFile = get(acceptedFiles, '[0]', []);
Object.assign(oneFile, { preview: URL.createObjectURL(oneFile) });
setFiles([oneFile, ...files]);
},
[files]
);

react hook, validate Form with reduxForm

I Have external component managing my input Field and throws an error if no input is made.
On submit of form previously with class component along with reduxForm effect, this would throw an error of missing input, am wondering how to achieve this with hooks since submission passes whether i have input or Not.
import ConstructField from '../components.render';
const ActivitiesForm = () => {
const handleSubmit_ = () => {
console.log({ activityName });
};
const [activityName, setActivityName] = useState(null);
const handleInputName = (e) => setActivityName(e.target.value);
const { items } = useSelector((state) => ({
items: state.items,
}));
const { register, handleSubmit, errors, control } = useForm();
return (
<div>
<Form onSubmit={handleSubmit(handleSubmit_)} className='ui form'>
<Form.Group widths='equal'>
<Field
component={ConstructField('input')}
onChange={handleInputName}
label='Activity Name'
name='activityName'
placeholder='Activity Name'
validate={required}
/>
</Form.Group>
<br />
<Form.Group inline>
<Button.Group>
<Button primary>Save</Button>
<Button.Or />
<Button positive onClick={goBackButton}>
Go Back
</Button>
</Button.Group>
</Form.Group>
</Form>
</div>
);
};
const required = (value) => (value ? undefined : 'this field is required');
const activityform = reduxForm({
form: 'activityform',
enableReinitialize: true,
})(ActivitiesForm);
export default activityform;

Filter features within map view React-Map-gl React Hooks

I'm quite new to React and JavaScript, am trying to write a queryRenderedFeatures filter for my React Hooks project using React-Map-gl.
The project has a huge list of data, and what I'd like to do is only filtering the data that appears within the map view. As this example shows on Mapbox-gl-js: https://docs.mapbox.com/mapbox-gl-js/example/filter-features-within-map-view/?q=geojson%20source&size=n_10_n
From the React-Map-gl's documentation: https://uber.github.io/react-map-gl/docs/api-reference/static-map#getmap
It says that you will be able to use queryRenderedFeatures as a method for a static map, but the way I've added it seems wrong... And there are not many resources online :/
Any help would be appreciated! :)
export default function Map() {
const [data, setData] = useState()
const [viewport, setViewport] = useState({
latitude: -28.016666,
longitude: 153.399994,
zoom: 12,
bearing: 0,
pitch: 0
})
const mapRef = useRef()
useEffect(() => {
fetch('../data.json')
.then(res => res.json())
.then(res => setData(res))
},[])
function features () {
mapRef.current.queryRenderedFeatures( { layers: ['ramps'] })
}
function filterRamps (e) {
data.features.filter(feature => {
return feature.properties.material === e.target.value
})
}
const handleClick = () => {
setData(filterRamps())
}
if (!data) {
return null
}
return (
<div style={{ height: '100%', position: 'relative' }}>
<MapGL
ref={mapRef}
{...viewport}
width="100%"
height="100%"
mapStyle="mapbox://styles/mapbox/dark-v9"
onViewportChange={setViewport}
mapboxApiAccessToken={Token}
queryRenderedFeatures={features}
>
<Source type="geojson" data={data}>
<Layer {...dataLayer} />
</Source>
</MapGL>
<Control
data={data}
onClick={handleClick}
/>
</div>
)
}
You need something like:
...
const mapRef = useRef()
...
<MapGL
ref={mapRef}
onClick={e => {
const features = mapRef.current.queryRenderedFeatures(e.geometry.coordinates, { layers: ['ramps'] })
console.log(features)
}}
...
/>

I am using antd deign to show select option but select cant read id provided and also cannot update onChange

I am using antd deign to show select option but select cant read id provided and also cannot update onChange.
import React from "react";
const data = {
orgName: "",
orgRegNo: "",
orgType: "",
orgTypes: [
{ id: "1", name: "Vendor" },
{ id: "2", name: "Supplier" },
{ id: "3", name: "Vendor and Supplier" }
]
};
export const MyContextTSX = React.createContext(data);
const Store = (props: any) => {
return (
<MyContextTSX.Provider value={data}>{props.children}</MyContextTSX.Provider>
);
};
export default Store;
//Next page of React signup
const signinData = useContext(MyContextTSX);
const [values, setValues] = useState(signinData);
<Select
id={values.orgTypes.id} //shows error while showing id
// name={values.orgTypes.name}
defaultValue="Choose"
style={{ width: 150 }}
onChange={(value: any) => //cant perform onChange
setValues({ ...value, name: value })
}
>
{values.orgTypes.map((option: any) => (
<Option
key={option.id}
value={option.name}
// onChange={handleChange}
>
{option.name}
</Option>
))}
</Select>
I am using antd deign to show select option but select cant read id provided and also cannot update onChange.
Link to CodeSandbox
There are few issues in your code.
Firstly, you are trying to access id from orgTypes which is an array. Instead you can defined a normal id.
Secondly, You need to have a contextProvider wrapping your App component
Third. You need to update state in the correct format such that you are not updating the data but the selected value. For that you need to have a state for selected value
Relavant code
index.js
ReactDOM(
<Store>
<App />
</Store>,
document.getElementById("root")
);
useForm.js
import { useContext, useState } from "react";
import { MyContextTSX } from "./Store";
const useForm = ({ callback }) => {
const values = useContext(MyContextTSX);
const [selected, setSelected] = useState({});
return { values, selected, setSelected };
};
export default useForm;
Register.js
const Register = () => {
const { values, selected, setSelected } = useForm({});
return (
<React.Fragment>
<Select
id={"select"} //shows error here
defaultValue="Choose"
style={{ width: 150 }}
onChange={(
value: any //what to do here ?
) => setSelected(selected)} //what to do here ?
>
{values.orgTypes.map((option: any) => (
<Option key={option.id} value={option.name}>
{option.name}
</Option>
))}
</Select>
<button onClick={() => console.log(values.orgTypes)}>Test</button>
</React.Fragment>
);
};
There are many problems with your code:
id={values.orgTypes.id} // orgTypes is an array, use values.orgTypes[0].id
---
onChange={(
value: any // value is the Select.Option value
) => setValues({ ...value, name: value })} // What exatcly you trying to do here?
Moreover, you don't specify types (and using Typescript).
Check this working example (Javascript):
const data = {
orgName: '',
orgRegNo: '',
orgType: '',
orgTypes: [
{ id: '1', name: 'Vendor' },
{ id: '2', name: 'Supplier' },
{ id: '3', name: 'Vendor and Supplier' }
]
};
const MyContextTSX = React.createContext(data);
function Signup() {
const signinData = useContext(MyContextTSX);
const [selected, setSelected] = useState();
return (
<div>
<h1>Selected: {selected}</h1>
<Select
defaultValue="Choose"
style={{ width: 150 }}
onChange={value => setSelected(value)}
>
{signinData.orgTypes.map(option => (
<Select.Option key={option.id} value={option.name}>
{option.name}
</Select.Option>
))}
</Select>
</div>
);
}
Demo:
Tweaking little bit #Dennish Vash answer and the signup function can also be written like this
function Signup() {
const signinData = useContext(MyContextTSX);
const [selected, setSelected] = useState();
return (
<div>
<h1>Selected: {selected}</h1>
<Select
defaultValue="Choose"
style={{ width: 150 }}
onChange={value => setSelected(value)}
>
{signinData.orgTypes.map(option => (
<Option value="{option.id}">{option.name}</Option>
))}
</Select>
</div>
);
}
Reference: https://github.dev/ant-design/ant-design/tree/master/components/select/demo

Resources