react-i18next how to style - internationalization

How would I style the emailString variable?
I want to make it bold OR use a className?
import { useTranslation } from "react-i18next";
const { t } = useTranslation("");
const emailAddress = "email#email.com"
<div>
{t("logoutCopy", { emailAddress: emailAddress })}
</div>

you can do this
<div>
<span style={{fontWeight:"bold"}}>
{t("logoutCopy", { emailAddress: emailAddress })}
</span/>
</div>
or
<div>
<span className="your_classname">
{t("logoutCopy", { emailAddress: emailAddress })}
</span/>
</div>

I solved this by using Trans.
import { Trans, useTranslation } from "react-i18next";
const { t } = useTranslation("foo");
<Trans t={t} i18nKey="logoutCopy" >
blah blah <span className={css.bold}>{{ emailAddress }}</span>. blah blah
</Trans>

Related

React-Bootstrap dynamic Image rendering

I am trying to display profile pic by calling the path and file name from database
Profile Image is not loading is it the path?
using json server local test.
Image is saved in folder ../src/image/
json data
image: "..image/pic.jpg"
import { Card, ListGroup } from "react-bootstrap";
import { useParams, useHistory } from "react-router-dom";
import useFetch from "./useFetch";
const MemberProfile = () => {
const { id } = useParams();
const {
data: member,
error,
isLoading,
} = useFetch("http://192.168.0.23:8000/members/" + id);
const history = useHistory();
const handleClick = () => {
fetch("http://192.168.0.23:8000/members/" + member.id, {
method: "DELETE",
}).then(() => {
history.push("/");
});
};
return (
<div className="memberProfile">
{isLoading && <div>Loading...</div>}
{error && <div>{error}</div>}
{member && (
<Card style={{}}>
<Card.Img variant="top" src={member.image} />
<Card.Body>
<Card.Title>
<h2>
<strong>
Profile - {member.name} {id}
</strong>
</h2>
</Card.Title>
<Card.Text>
<pre className="acordnBody">
Gender : {member.gender} <hr />
Phone : {member.tel} <hr />
E-mail : {member.email} <hr />
Address : {member.address}
</pre>
</Card.Text>
</Card.Body>
</Card>
)}
</div>
);
};
export default MemberProfile;

use of mapstatetoprops and mapdispatchtoprops in react final form

I have an application where I have used redux-form version 5.3.6, now I want to migrate from it to react-final-form. As I have mostly used Redux to manage form data while using redux-form, now while I am migrating, I find it very hard to integrate my redux codes with the final form implementation mentioned in the migration doc: https://final-form.org/docs/react-final-form/migration/redux-form
I am finding it difficult to use my mapStateToProps, mapDispatchToProps, and other redux-related functions with the final-form implementation.
Here is my current form container code from where form data is getting connected with redux via redux-form
import React from 'react';
import PropTypes from 'prop-types';
import { reduxForm } from 'redux-form';
import moment from 'moment';
import { startFromCart, endFromCart } from '../../lib/datesFromCart';
import { validateAllSearchParams } from './helpers/validate';
import cartOverride from './helpers/cartOverride';
import deepClone from '../../lib/deepClone';
import SearchForm from './SearchForm';
import searchAccountValues from '../../helpers/searchAccountValues';
import { createCarSearch } from '../../actions/car';
import { resetApp } from '../../actions/common';
const initialFields = [
'pickUpDate',
'dropOffDate',
'pickUpTime',
'dropOffTime',
'airportSearch',
'pickUpLocationAirportCode',
'pickUpGeoLocationAddress',
'pickUpGeoLocationLatitude',
'pickUpGeoLocationLongitude',
'dropOffLocationAirportCode',
'dropOffGeoLocationAddress',
'dropOffGeoLocationLatitude',
'dropOffGeoLocationLongitude',
'driverAge',
'vendorPreferences.codes',
'vendorPreferences.type',
];
const reduxFormConfig = {
form: 'carSearchForm',
destroyOnUnmount: false,
fields: [],
};
const mapStateToProps = (state, ownProps) => {
const { adults } = state.common.travelerCount;
const fields = deepClone(initialFields);
const cartHasCar = state.common.cart.items.some(item => item.type === 'car');
if (ownProps.searchAccounts && ownProps.searchAccounts.cars) {
Object.keys(ownProps.searchAccounts.cars).forEach(key => fields.push(`accountSettings.${key}`));
}
const startDateFromCart = startFromCart(state);
const endDateFromCart = endFromCart(state);
let vendorsPreferences = []
if (ownProps.globalPolicyPreferences.carRentalCompanies.length > 0) {
vendorsPreferences = ownProps.globalPolicyPreferences.carRentalCompanies
}
const defaultSearchParams = {
accountSettings: searchAccountValues(ownProps.searchAccounts.cars),
airportSearch: false,
driverAge: ownProps.currentUserAge || 32,
pickUpDate:
startDateFromCart ||
state.cars.defaultCarSearchParams.pickUpDate ||
moment()
.add(7, 'days')
.startOf('day')
.format('YYYY-MM-DD'),
dropOffDate: endDateFromCart || state.cars.defaultCarSearchParams.dropOffDate,
pickUpTime: '12:00',
dropOffTime: '11:00',
vendorPreferences: state.cars.defaultCarSearchParams.vendorPreferences || {
codes: vendorsPreferences,
type: 'exclusive',
},
};
const searchForm = state.form.carSearchForm;
const preselectTravelers = state.common.preselectTravelers.travelers;
const cartHasItems = state.common.cart.items.length > 0;
return {
fields,
cartHasCar,
initialValues: {
...defaultSearchParams,
...ownProps.searchParams,
...state.cars.defaultCarSearchParams,
...cartOverride(adults),
},
validate: validateAllSearchParams(ownProps.availableChannels.cars, ownProps.minHoursInFuture),
defaultSearchParams,
preselectTravelers,
searchForm,
cartHasItems,
travelerLoggedIn: ownProps.travelerLoggedIn,
};
};
const mapDispatchToProps = dispatch => ({
createCarSearch: (params, callbacks) => dispatch(createCarSearch(params, callbacks)),
resetApp: () => dispatch(resetApp('/cars')),
});
const ReduxForm = reduxForm(reduxFormConfig, mapStateToProps, mapDispatchToProps)(SearchForm);
const SearchFormWithContext = (props, context) => <ReduxForm {...props} {...context} />;
SearchFormWithContext.contextTypes = {
availableChannels: PropTypes.object,
searchAccounts: PropTypes.object,
laymanMode: PropTypes.bool,
currency: PropTypes.string,
callbackParams: PropTypes.object,
minHoursInFuture: PropTypes.number.isRequired,
currentUserAge: PropTypes.number.isRequired,
globalPolicyPreferences: PropTypes.shape({
airlines: PropTypes.arrayOf(PropTypes.number).isRequired,
carRentalCompanies: PropTypes.arrayOf(PropTypes.number).isRequired,
}).isRequired,
};
export default SearchFormWithContext;
The component is
import React, { useEffect, Fragment, useState } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import moment from 'moment';
import { I18nText } from '#wtag/react-comp-lib';
import { Menu, MenuItem } from '#wtag/rcl-menu';
import Alert from '#wtag/rcl-alert';
import SelectBox from '#wtag/rcl-select-box';
import Input from '#wtag/rcl-input';
import Button from '#wtag/rcl-button';
import Icon from '#wtag/rcl-icon';
import LocationSearchInput from 'sharedWebpack/LocationSearchInput';
import DatePickerWithFocusedStateWrapper from 'sharedWebpack/DatePickerWithFocusedStateWrapper';
import TimeSelectBox from 'sharedWebpack/TimeSelectBox';
import availableChannelsShape from '../../shapes/availableChannels';
import noChannelSelected from '../../lib/helpers/noChannelSelected';
import showInvalidDateError from '../../helpers/showInvalidDateError';
import history from '../../lib/history';
import { showError } from '../../actions/common';
import AirportAutoComplete from '../AirportAutoComplete';
import VendorSelectBox from './VendorSelectBox';
import SearchAccounts from '../../components/SearchAccounts';
import searchAccountsShape from '../../shapes/searchAccounts';
import PreselectTravelers from '../PreselectTravelers';
import preparePreselectTravelers from '../PreselectTravelers/preparePreselectTravelers';
import useSearchFormContainer from '../../helpers/hooks/useSearchFormContainer';
const SearchForm = props => {
const {
fields: {
airportSearch,
pickUpLocationAirportCode,
dropOffLocationAirportCode,
pickUpGeoLocationAddress,
pickUpGeoLocationLatitude,
pickUpGeoLocationLongitude,
dropOffGeoLocationAddress,
dropOffGeoLocationLatitude,
dropOffGeoLocationLongitude,
pickUpDate,
dropOffDate,
pickUpTime,
dropOffTime,
driverAge,
vendorPreferences,
accountSettings,
},
submitting,
handleSubmit,
laymanMode,
availableChannels,
cartHasCar,
createCarSearch,
defaultSearchParams,
initializeForm,
globalPolicyPreferences,
resetApp,
searchForm,
preselectTravelers,
setIsCollapsed,
cartHasItems,
formWithoutChildren,
resetBookingAppContext,
travelerLoggedIn,
travelArrangerPresent,
} = props;
const [isLocationMenuVisible, setIsLocationMenuVisible] = useState(false);
const [isVendorMenuVisible, setIsVendorMenuVisible] = useState(false);
const [isAgeMenuVisible, setIsAgeMenuVisible] = useState(false);
const onLocationMenuOutsideClick = () => {
setIsLocationMenuVisible(false);
};
const onVendorMenuOutsideClick = () => {
setIsVendorMenuVisible(false);
};
const onAgeMenuOutsideClick = () => {
setIsAgeMenuVisible(false);
};
const showCarFormContainer = useSearchFormContainer();
const filterTypeOptions = [
{
value: 'preferred',
label: I18n.t('components.ibe.search_form.car.label.vendor_preferences_type.preferred'),
isDisabled: laymanMode
? availableChannels.cars.includes('galileo')
: accountSettings && accountSettings.galileo && accountSettings.galileo.value.length > 0,
},
{
value: 'exclusive',
label: I18n.t('components.ibe.search_form.car.label.vendor_preferences_type.exclusive'),
},
];
const disableVendorPreference = globalPolicyPreferences.carRentalCompanies.length > 0;
const isNoChannelSelected = noChannelSelected(
laymanMode,
availableChannels,
accountSettings,
'cars',
);
const onPickUpLocationSelect = (address, latitude, longitude) => {
if (!dropOffGeoLocationAddress.touched) {
dropOffGeoLocationAddress.onChange(address);
dropOffGeoLocationLatitude.onChange(latitude);
dropOffGeoLocationLongitude.onChange(longitude);
}
};
const onPickUpAirportChange = airport => {
pickUpLocationAirportCode.onChange(airport);
if (!dropOffLocationAirportCode.touched) {
dropOffLocationAirportCode.onChange(airport);
}
};
const onPickUpDateChange = date => {
if (date === '') {
pickUpDate.onChange('');
} else {
const pickUpDateValue = moment.utc(date);
pickUpDate.onChange(pickUpDateValue.format());
if (!dropOffDate.touched) {
const nextValue = pickUpDateValue.add(7, 'days').format();
dropOffDate.onChange(nextValue);
}
}
};
const handleFormSubmission = (values, dispatch, ownProps) => {
history.push('/cars/searching');
createCarSearch(
{
...values,
currency: ownProps.currency,
preselectTravelers: preparePreselectTravelers(preselectTravelers),
},
ownProps.callbackParams,
)
.then(data => data && data.id && history.push(`/cars/searches/${data.id}`))
.catch(error => dispatch(showError('Search failed for unknown reasons', error)));
setIsCollapsed();
};
const resetToDefaultSearchParams = () => {
initializeForm(defaultSearchParams);
};
const findTimeSelectBoxValue = value => {
if (value === 'anytime') {
return { label: <I18nText id="departure_times.anytime" />, value };
}
return { label: value, value };
};
const onDropOffDateChange = date => {
if (date === '') {
dropOffDate.onChange('');
} else if (date) {
dropOffDate.onChange(moment.utc(date).format());
}
};
const minDropOffDate = () => {
if (pickUpDate.value) return moment(pickUpDate.value).add(1, 'days');
return moment()
.add(1, 'days')
.format('YYYY/MM/DD');
};
const updateDriverAgeFromPreselectedTraveler = () => {
const driver = preselectTravelers[0];
if (driver.traveler.value.age) {
driverAge.onChange(driver.traveler.value.age);
}
};
const loggedInTravellerConditions = travelerLoggedIn && travelArrangerPresent;
const guestTravellerConditions = !travelerLoggedIn && !cartHasItems && formWithoutChildren;
const showPreselectTravellerButton = () => {
if (
laymanMode &&
(loggedInTravellerConditions || guestTravellerConditions) &&
!props.forceAdvancedSearch
) {
return <PreselectTravelers type="car" />;
}
return null;
};
useEffect(() => {
const vendorCodes = globalPolicyPreferences.carRentalCompanies;
if (vendorCodes.length > 0) {
vendorPreferences.codes.onChange(vendorCodes);
vendorPreferences.type.onChange('exclusive');
}
}, []);
useEffect(() => {
if (!searchForm) {
resetToDefaultSearchParams();
}
}, [searchForm]);
useEffect(() => {
if (!driverAge.touched && preselectTravelers.length > 0) {
updateDriverAgeFromPreselectedTraveler();
}
}, [preselectTravelers]);
return (
<div
className={classNames('grid car-form__container', {
'car-form__container--show': showCarFormContainer,
})}
>
<div className="col-grid direction-row col-12 car-form__specifier-container wrap">
<div className="search-menu__container search-menu__container--location">
<Menu
className="search-menu__container--location-dropdown"
isVisible={isLocationMenuVisible}
size="small"
popOverDirection="bottom-left"
onOutsideClick={onLocationMenuOutsideClick}
label={
<div className="search-menu__menu-label">
{airportSearch.value
? I18n.t('components.ibe.search_form.car.label.search_by.airport')
: I18n.t('components.ibe.search_form.car.label.search_by.location')}
<div
className="search-menu__menu-label--icon"
onClick={() => setIsLocationMenuVisible(prevState => !prevState)}
role="button"
tabIndex={0}
onKeyPress={() => setIsLocationMenuVisible(prevState => !prevState)}
>
<Icon name="iconDownChevron" size="tiny" />
</div>
</div>
}
>
<MenuItem
onClick={() => {
airportSearch.onChange(false);
setIsLocationMenuVisible(false);
}}
>
{I18n.t('components.ibe.search_form.car.label.search_by.location')}
</MenuItem>
<MenuItem
onClick={() => {
airportSearch.onChange(true);
setIsLocationMenuVisible(false);
}}
>
{I18n.t('components.ibe.search_form.car.label.search_by.airport')}
</MenuItem>
</Menu>
</div>
<div className="search-menu__container search-menu__container--vendors">
<Menu
className="search-menu__container--vendors-dropdown"
isVisible={isVendorMenuVisible}
size="small"
popOverDirection="bottom-center"
onOutsideClick={onVendorMenuOutsideClick}
label={
<div className="search-menu__menu-label">
{I18n.t('components.ibe.search_form.car.label.vendor_preferences')}
<div
className="search-menu__menu-label--icon"
onClick={() => setIsVendorMenuVisible(prevState => !prevState)}
role="button"
tabIndex={0}
onKeyPress={() => setIsVendorMenuVisible(prevState => !prevState)}
>
<Icon name="iconDownChevron" size="tiny" />
</div>
</div>
}
>
<div className="search-menu-item__container">
<div className="search-menu-item__specifier">
<div className="col-12 col-bleed">
<div className="search-menu-item__specifier--add-padding-bottom">
<VendorSelectBox
value={vendorPreferences.codes.value}
onChange={value => vendorPreferences.codes.onChange(value || [])}
errorMsg={vendorPreferences.codes.error && vendorPreferences.codes.error[0]}
isMulti={true}
width="full"
size="tiny"
placeholderText={I18n.t('components.ibe.search_form.car.label.choose_vendor')}
isDisabled={disableVendorPreference}
/>
</div>
<SelectBox
width="full"
size="tiny"
value={filterTypeOptions.find(
filter => filter.value === vendorPreferences.type.value,
)}
isDisabled={
disableVendorPreference || vendorPreferences.codes.value.length <= 0
}
options={filterTypeOptions}
onChange={selectedOption =>
vendorPreferences.type.onChange(selectedOption ? selectedOption.value : '')
}
placeholderText={I18n.t('components.ibe.search_form.car.label.filter_type')}
isClearable={false}
/>
</div>
</div>
</div>
</Menu>
</div>
<div className="search-menu__container search-menu__container--drivers-age">
<Menu
className="search-menu__container--drivers-age-dropdown"
isVisible={isAgeMenuVisible}
size="small"
popOverDirection="bottom-center"
onOutsideClick={onAgeMenuOutsideClick}
label={
<div
className={classNames('search-menu__menu-label', {
'search-menu__label--error': driverAge.touched && !driverAge.valid,
})}
>
{I18n.t('components.ibe.search_form.car.label.driver_age')}
<div
className="search-menu__menu-label--icon"
onClick={() => setIsAgeMenuVisible(prevState => !prevState)}
role="button"
tabIndex={0}
onKeyPress={() => setIsAgeMenuVisible(prevState => !prevState)}
>
<Icon name="iconDownChevron" size="tiny" />
</div>
</div>
}
>
<div className="search-menu-item__container">
<div className="search-menu-item__specifier">
<div className="col-12 col-bleed">
<Input
placeholder={I18n.t('components.ibe.search_form.car.label.driver_age')}
size="tiny"
type="number"
{...driverAge}
disabled={cartHasCar}
/>
</div>
</div>
<Alert
className="col-12 col-bleed car-form__error"
hideClose={true}
isLocationMenuVisible={cartHasCar}
type="warning"
>
{I18n.t('components.ibe.search_form.error.change_number_of_travelers')}
</Alert>
</div>
</Menu>
</div>
</div>
<div className="col-12 col-bleed-y">
{airportSearch.value ? (
<Fragment>
<div className="col-12 col-sm-6 col-bleed car-form__field--add-padding-right">
<AirportAutoComplete
title={I18n.t('components.ibe.search_form.car.label.pick_up.airport')}
error={pickUpLocationAirportCode.touched && pickUpLocationAirportCode.error}
currentAirport={pickUpLocationAirportCode.value}
{...pickUpLocationAirportCode}
onChange={onPickUpAirportChange}
fullWidth={true}
size="tiny"
/>
</div>
<div className="col-12 col-sm-6 col-bleed car-form__field--add-padding-left">
<AirportAutoComplete
title={I18n.t('components.ibe.search_form.car.label.drop_off.airport')}
error={dropOffLocationAirportCode.error}
currentAirport={dropOffLocationAirportCode.value}
{...dropOffLocationAirportCode}
fullWidth={true}
/>
</div>
</Fragment>
) : (
<Fragment>
<div className="col-12 col-sm-6 col-bleed car-form__field--add-padding-right">
<LocationSearchInput
address={pickUpGeoLocationAddress.value}
placeholder={I18n.t('components.ibe.search_form.car.label.pick_up.location')}
fullWidth={true}
onAddressChange={pickUpGeoLocationAddress.onChange}
onLatitudeChange={pickUpGeoLocationLatitude.onChange}
onLongitudeChange={pickUpGeoLocationLongitude.onChange}
onSelect={onPickUpLocationSelect}
size="small"
touched={pickUpGeoLocationAddress.touched}
error={pickUpGeoLocationAddress.error}
/>
</div>
<div className="col-12 col-sm-6 col-bleed car-form__field--add-padding-left">
<LocationSearchInput
address={dropOffGeoLocationAddress.value}
placeholder={I18n.t('components.ibe.search_form.car.label.drop_off.location')}
fullWidth={true}
onAddressChange={dropOffGeoLocationAddress.onChange}
onLatitudeChange={dropOffGeoLocationLatitude.onChange}
onLongitudeChange={dropOffGeoLocationLongitude.onChange}
size="small"
touched={dropOffGeoLocationAddress.touched}
error={dropOffGeoLocationAddress.error}
/>
</div>
</Fragment>
)}
</div>
<div className="col-12">
<div className="col-12 col-sm-6 col-bleed car-form__field--add-padding-right">
<DatePickerWithFocusedStateWrapper
pastYearsCount={0}
futureYearsCount={1}
size="small"
hideMonthsAndYearsWithNoActiveDates={true}
id={Math.random()}
placeholder={I18n.t('components.ibe.search_form.car.label.pick_up.date')}
onChange={onPickUpDateChange}
fullWidth={true}
error={showInvalidDateError(pickUpDate)}
minDate={moment()
.add(1, 'days')
.format('YYYY/MM/DD')}
date={pickUpDate.value}
locale={moment().locale()}
showClearDate={true}
hideNavButtons={false}
/>
</div>
<div className="col-12 col-sm-6 col-bleed car-form__field--add-padding-left">
<TimeSelectBox
placeholderText={I18n.t('components.ibe.search_form.car.label.pick_up.time')}
width="full"
onChange={selectedOption => selectedOption && pickUpTime.onChange(selectedOption.value)}
errorMsg={pickUpTime.touched && pickUpTime.error}
value={findTimeSelectBoxValue(pickUpTime.value)}
isClearable={false}
size="small"
/>
</div>
</div>
<div className="col-12 col-bleed-y">
<div className="col-12 col-sm-6 col-bleed car-form__field--add-padding-right">
<DatePickerWithFocusedStateWrapper
pastYearsCount={0}
futureYearsCount={1}
size="small"
hideMonthsAndYearsWithNoActiveDates={true}
id={Math.random()}
placeholder={I18n.t('components.ibe.search_form.car.label.drop_off.date')}
onChange={onDropOffDateChange}
fullWidth={true}
error={showInvalidDateError(dropOffDate)}
minDate={minDropOffDate()}
date={dropOffDate.value}
locale={moment().locale()}
showClearDate={true}
hideNavButtons={false}
/>
</div>
<div className="col-12 col-sm-6 col-bleed car-form__field--add-padding-left">
<TimeSelectBox
placeholderText={I18n.t('components.ibe.search_form.car.label.drop_off.time')}
width="full"
onChange={selectedOption =>
selectedOption && dropOffTime.onChange(selectedOption.value)
}
errorMsg={dropOffTime.touched && dropOffTime.error}
value={findTimeSelectBoxValue(dropOffTime.value)}
isClearable={false}
size="small"
/>
</div>
</div>
{!props.laymanMode && (
<div className="col-12 car-form__search-accounts">
<div className="accounts">
<SearchAccounts
searchAccounts={props.searchAccounts.cars}
selectedAccounts={accountSettings}
disabled={false}
selectAll={props.selectAll}
toggleSelectAll={props.toggleSelectAll}
selectGds={props.selectGds}
toggleSelectGds={props.toggleSelectGds}
selectDirect={props.selectDirect}
toggleSelectDirect={props.toggleSelectDirect}
/>
</div>
</div>
)}
<Alert
className="col-12 col-bleed hotel-form__error"
hideClose={true}
isLocationMenuVisible={isNoChannelSelected}
type="danger"
>
{I18n.t('components.ibe.search_form.error.no_channel_selected')}
</Alert>
<div className="col-grid direction-row align-center justify-space-between hotel-form__action-wrapper">
<div className="car-form__preselect-traveler">{showPreselectTravellerButton()}</div>
<div className="car-form__action">
<div className="hotel-form__field--add-padding-right">
<Button
label={I18n.t('components.ibe.search_form.label.reset')}
size="normal"
version="v2"
onClick={() => {
resetApp();
resetBookingAppContext();
}}
/>
</div>
<div className="hotel-form__field--add-padding-left">
<Button
label={I18n.t('components.ibe.search_form.label.search')}
size="normal"
version="v2"
disabled={!!submitting || isNoChannelSelected}
onClick={handleSubmit(handleFormSubmission)}
type="primary"
/>
</div>
</div>
</div>
</div>
);
};
export default SearchForm;
the corresponding reducer is
import { combineReducers } from 'redux';
import defaultCarSearchParams from './defaultCarSearchParams';
import searchFilterParamsBySearchId from './searchFilterParamsBySearchId';
import searchParamsBySearchId from './searchParamsBySearchId';
import searchResultsBySearchId from './searchResultsBySearchId';
import searchStatsBySearchId from './searchStatsBySearchId';
import totalResultsBySearchId from './totalResultsBySearchId';
import vendorsByCode from './vendorsByCode';
import totalResultsPerSupplier from './totalResultsPerSupplier'
const carsReducer = combineReducers({
defaultCarSearchParams,
searchFilterParamsBySearchId,
searchParamsBySearchId,
searchResultsBySearchId,
searchStatsBySearchId,
totalResultsBySearchId,
vendorsByCode,
totalResultsPerSupplier,
});
export default carsReducer;
Now I am not sure how to make migration among these from redux-form to react-final-form using my Redux codes.

Form is not rendered

I'm making a todo app and using useState to pass value to the form then submit the todo but for some reasons my todo form is not render and i don't know what is missing in my codes, please help me to check! Thank you so much!
import React, { useState } from "react";
function Todo({ todo, index }) {
console.log("hiiii");
return (
<div>
<p>{todo.text}</p>
</div>
);
}
function todoForm(addTodo) {
const [value, setValue] = useState("");
handleSubmit = (e) => {
e.preventDefault();
if (!value) return;
addTodo(value);
setValue("");
};
return (
<div>
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="add new todo"
value={value}
onChange={(e) => {
setValue(e.target.value);
}}
/>
</form>
</div>
);
}
function App() {
const [todos, setTodos] = useState([
{
text: "eat lunch",
isCompleted: false
},
{
text: "do homework",
isCompleted: false
},
{
text: "go to school",
isCompleted: false
}
]);
addTodo = (text) => {
console.log("hey");
const newTodos = [...todos, { text }];
setTodos(newTodos);
};
return (
<div>
<div>
{todos.map((todo, index) => {
return <Todo key={index} index={index} todo={todo} />;
})}
</div>
<div>
<todoForm addTodo={addTodo} />
</div>
</div>
);
}
export default App;
Link sandbox: https://codesandbox.io/s/serverless-bash-ef4hk?file=/src/App.js
JSX tags must be uppercased in order to be properly parsed by the compiler as a React component.
Instead of todoForm, use TodoForm.
Capitalized types indicate that the JSX tag is referring to a React component. These tags get compiled into a direct reference to the named variable, so if you use the JSX expression, Foo must be in scope.
From: https://reactjs.org/docs/jsx-in-depth.html#specifying-the-react-element-type
Also, you need to destructure props inside TodoForm in order to gain access to addTodo:
// Bad
function TodoForm(addTodo) {...}
// Good
function TodoForm({addTodo}) {...}
You should also assign you handlers to consts:
// Bad
addTodo = (text) => {...};
// Good
const addTodo = (text) => {...};
your problem is solved it
APP.JS
import React, { useState } from "react";
function Todo({ todo, index }) {
console.log("hiiii");
return (
<div>
<p>{todo.text}</p>
</div>
);
}
function todoForm(addTodo) {
const [value, setValue] = useState("");
const handleSubmit = (e) => {
e.preventDefault();
if (!value) return;
addTodo(value);
setValue("");
};
return (
<div>
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="add new todo"
value={value}
onChange={(e) => {
setValue(e.target.value);
}}
/>
</form>
</div>
);
}
function App() {
const [todos, setTodos] = useState([
{
text: "eat lunch",
isCompleted: false
},
{
text: "do homework",
isCompleted: false
},
{
text: "go to school",
isCompleted: false
}
]);
const addTodo = (text) => {
console.log("hey");
const newTodos = [...todos, { text }];
setTodos(newTodos);
};
return (
<div>
<div>
{todos.map((todo, index) => {
return <Todo key={index} index={index} todo={todo} />;
})}
</div>
<div>
{todoForm(addTodo)}
</div>
</div>
);
}
export default App;

GraphQL mutation on Form Click not triggering

I am trying to call Apollo Mutation Hook on form submit to create a new record in the database.
export default function NewJobForm() {
const { loading, error, data } = useQuery(GET_LOC_CAT_TYPE_QUERY);
const [newJob] = useMutation(NEW_JOB_MUTATION);
const [remote, setRemote] = useState(false);
const editorRef = useRef(null);
const log = () => {
if (editorRef.current) {
console.log(editorRef.current.getContent());
}
};
let initialFormValues = {
companyName: '',
title: '',
};
const JobSchema = yup.object({
companyName: yup.string().required('Please enter the company name.'),
title: yup.string().required('Please enter the job title.'),
});
let formValidate = (values) => {
console.log(values);
const errors = {};
return errors;
};
let handleError = (field, actions) => {
field.forEach((data) => {
let field = data.param;
switch (field) {
// case 'name':
// actions.setFieldError('name', data.msg);
// break;
default:
break;
}
});
};
let formSubmit = async (values, actions) => {
console.log(values);
newJob({ variables: values });
};
return (
<>
<Formik
validationSchema={JobSchema}
validate={(values) => formValidate(values)}
onSubmit={(values, actions) => formSubmit(values, actions)}
enableReinitialize={true}
initialValues={initialFormValues}
validateOnChange={true}
validateOnBlur={false}
>
{({ handleSubmit, setFieldValue, values }) => (
<form noValidate onSubmit={handleSubmit}>
<div className="space-y-8 divide-y divide-gray-200">
<div>
<div>
<h3 className="text-lg font-medium leading-6 text-gray-900">
Job Details
</h3>
<p className="mt-1 text-sm text-gray-500">
This information will be displayed
publicly so be careful what you share.
</p>
</div>
<div className="grid grid-cols-1 mt-6 gap-y-6 gap-x-4 sm:grid-cols-6">
<div className="sm:col-span-4">
<TextInput
label="Company Name"
id="companyName"
name="companyName"
type="text"
placeholder="eg: Google"
helpText="Please Enter the name of the company"
/>
</div>
<div className="sm:col-span-4">
<TextInput
label="Job Title"
id="title"
name="title"
type="text"
/>
</div>
</div>
</div>
</div>
</form>
)}
</Formik>
</>
);
}
On Form Submit the console.log displays the message but the mutation network call does not seem to get triggered.

How to Display search result on another page in react hooks

I m developing an e-commerce application with react hooks in search component result is shown beneath the component I want to render on search Result component how to redirect search result on the search Result component
import React, { useState, useEffect } from "react";
import { Link, Redirect } from "react-router-dom";
import { getCategories, list } from "./apiCore";
import SearchResult from "./SearchResult";
const Search = () => {
const [data, setData] = useState({
categories: [],
category: "",
search: "",
results: [],
searched: false,
});
const { categories, category, search, results, searched } = data;
const loadCategories = () => {
getCategories().then(data => {
if (data.error) {
console.log(data.error);
} else {
setData({ ...data, categories: data });
}
});
};
useEffect(() => {
loadCategories();
}, []);
const searchData = () => {
// console.log(search, category);
if (search) {
list({ search: search || undefined, category: category }).then(
response => {
if (response.error) {
console.log(response.error);
} else {
setData({ ...data, results: response, searched: true });
}
}
);
}
};
const searchSubmit = e => {
e.preventDefault();
searchData();
};
const handleChange = name => event => {
setData({ ...data, [name]: event.target.value, searched: false });
};
const searchMessage = (searched, results) => {
if (searched && results.length > 0) {
return `Found ${results.length} products`;
}
if (searched && results.length < 1) {
return `No products found`;
}
};
const searchedProducts = (results = []) => {
return (
<div>
<h2 className="text-muted mb-4">
{searchMessage(searched, results)}
</h2>
<div className="row">
{results.map((product, i) => (
<CarouselCard key={i} product={product} />
))}
</div>
</div>
);
};
return (
<div className="site-navbar-top">
<div className="container">
<div className="row align-items-center">
<div className="col-6 col-md-4 order-2 order-md-1 site-search-icon text-left">
<form className="site-block-top-search" onSubmit={searchSubmit}>
<span className="icon icon-search2"></span>
<input type="text" className="form-control border-0" placeholder="Search" onChange={handleChange("search")} />
</form>
</div>
<div className="col-12 mb-3 mb-md-0 col-md-4 order-1 order-md-2 text-center">
<div className="site-logo">
<Link to="/" className="js-logo-clone">Shoppers</Link>
</div>
</div>
<div className="col-6 col-md-4 order-3 order-md-3 text-right">
<div className="site-top-icons">
<ul>
<li><Link to="#"><span className="icon icon-person" /></Link></li>
<li><Link to="#"><span className="icon icon-heart-o" /></Link></li>
<li>
<Link to="cart.html" className="site-cart">
<span className="icon icon-shopping_cart" />
<span className="count">2</span>
</Link>
</li>
</ul>
</div>
</div>
</div>
</div>
{searchedProducts(results)}
</div>
)
}
export default Search;
The main part of the hook is pretty straightforward, but I'm having a difficult time finding a nice way to handle that redirect. The current working solution is to wrap the functional component with withRouter, then pass props.history

Resources