Editing immutable state items - javascript

I'm trying to update some immutable data. However, I am doing it incorrectly and it doesn't work.
My understanding, is I need to pass it a unique it (eg the key) so it knows which item in state to update. But this may be wrong, and I would like to do this the proper way. I tried the immutability helper, but had no success.
I will also want to update/add/remove nested items in an immutable array.
I put this in a codeSandbox for ease https://codesandbox.io/s/mz5WnOXn
class App extends React.Component {
...
editTitle = (e,changeKey) => {
this.setState({
movies: update(this.state.movies, {changeKey: {name: {$set: e.target.value}}})
})
console.log('Edit title ran on', key)
};
...
render() {
...
return (
<div>
{movies.map(e => {
return (
<div>
<input key={e.pk} onChange={this.editTitle} value={e.name} changeKey={e.pk} type="text" />
With genres:
{e.genres.map(x => {
return (
<span key={x.pk}>
<input onChange={this.editGenres} value={x.name} changeKey={x.pk} type="text" />
</span>
);
})}
</div>
);
})}
</div>
);
}
}

Couple of things,
1. By looking at your data i don't see any pk property maybe its a typo (are you trying to use the id property instead?).
2. The key prop should be on the root element that you return on each iteration of your map function.
3. You can't just add none native attributes to a native Html element instead you can use the data-* like data-changeKey and access it via e.target.getAttribute('data-changeKey')
Something like this:
import { render } from 'react-dom';
import React from 'react';
import { reject, pluck, prop, pipe, filter, flatten, uniqBy } from 'ramda';
import { smallData } from './components/data.js';
import './index.css';
import Result from './components/Result';
import update from 'react-addons-update';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
movies: smallData.movies,
selectedFilters: {},
searchQuery: '',
};
}
editTitle = (e) => {
const attr = e.target.getAttribute('data-changeKey');
this.setState({
movies: update(this.state.movies, {
// what are you trying to do here?
//changeKey: { name: { $set: e.target.value } },
}),
});
console.log('edit title ran on', attr);
};
onSearch = e => {
this.setState({
searchQuery: e.target.value,
});
};
render() {
const { movies } = this.state;
return (
<div>
{movies.map((e, i) => {
return (
<div key={i}>
<input
onChange={this.editTitle}
value={e.name}
data-changeKey={e.id}
type="text"
/>
With genres:
{e.genres.map((x,y) => {
return (
<span key={y}>
<input
onChange={this.editTitle}
value={x.name}
data-changeKey={x.id}
type="text"
/>
</span>
);
})}
Add new genre:
<input type="text" />
</div>
);
})}
</div>
);
}
}
render(<App />, document.getElementById('root'));

Index is what update needs in order to know which data to change.
Firstly, map sure your map is creating an index:
{movies.map((e,index) => {
return (
<input key={e.pk} onChange={e => this.editTitle(e, index)} value={e.name} >
...
Then pass the index to the immutability-helper update like so:
to:
editTitle = (e, index) => {
this.setState({
movies: update(this.state.movies, {[index]: {name: {$set: e.target.value}}})
})

Related

change object into array present another component in react

i am sorry for the very basic question as i m new to react js. i have created an array in a react component and render it through map function in one component and i want to change (add/Subject) in the array from an other component on basis of _id. the following is a sample that helps you better to understand what i actually want. Thanks in advance Sir
{*Array Component*}
const ArrayData =[
{
_id:1,
title:"All Searches"
},
{
_id:5,
title:1
},
{
_id:6,
title:"4"
}
]
export default ArrayData;
{*2nd Component*}
import react from "react"
import ArrayData from ArrayComponent
class Parent extends React.Component {
constructor() {
super();
this.state = {
ArrayData:ArrayData,
collapsed: false,
}
}
render() {
const { ArrayData } = this.state;
return (
<>
<FirstChild Data={ArrayData} />
<SecondChild />
</>
);
}
}
export default Parent;
!------------------------------------------!
{*FirstChild*}
class FirstChild extends React.Component {
constructor(props){
super();
this.state={
ArrayData:props.ArrayData
}
}
render() {
const { ArrayData} = this.state;
const renderArray = ArrayData.slice(0, 5).map(Object => {
return <h1>{object._id} </h1>
})
return (
<>
{renderArray}
</>
);
}
}
export default FirstChild;
!-----------------------------------------!
{*SecondChild*}
import { React } from "react";
const SecondChild = () => {
const handleUpdate=(_id, Title) =>{
{*function that can add the inputs as a object into that arrayComponent*}
}
const handleDelete=(_id) =>{
{*function that can delete a object from that arrayComponent having the id given by User in the feild*}
}
return (
<>
<input type='text' name='_id' placeHolder="Which object you want to delete" />
<button type=Submit onClick={handleDelete} >Delete</button>
<br></br>
<input type='text' name='_id' />
<input type='text' name='title' />
<button type=Submit onClick={handleUpdate} >Update</button>
</>
);
}
export default SecondChild;
CODESANDBOX
All you need to do is declare handleDelete and handleUpdate on the Parent component and pass it as a props in SecondChild component. If we place state and its methods in Parent component, then it is easy to track, debug, and easy to maintain. It would be easy to pass the methods if we define another component, let say ThirdComponent and it also contains functionality to perform CRUD operation on the ArrayData array.
In the FirstChild component, you were destructuring the ArrayData const { ArrayData} = this.state; and using it in the render method. It won't update we receive new props because you are rendering the array state that gets created once(as a constructor will get called once) and we want the latest value of ArrayData from the parent component. We can use props directly in the render method. You need to see the react lifecycle methods.
Parent.js
import React from "react";
import ArrayData from "./ArrayComponent";
import FirstChild from "./FirstChild";
import SecondChild from "./SecondChild";
class Parent extends React.Component {
constructor() {
super();
this.state = {
ArrayData: ArrayData,
collapsed: false
};
this.handleDelete = this.handleDelete.bind(this);
this.handleUpdate = this.handleUpdate.bind(this);
}
handleDelete(id) {
const idToDelete = parseInt(id, 10);
this.setState((state) => {
const filteredArrayData = state.ArrayData.filter(
(el) => el._id !== idToDelete
);
return {
ArrayData: filteredArrayData
};
});
}
handleUpdate(newObj) {
console.log(newObj);
this.setState((state) => ({
ArrayData: [...state.ArrayData, newObj]
}));
}
render() {
return (
<>
<FirstChild Data={this.state.ArrayData} />
<SecondChild
handleUpdate={this.handleUpdate}
handleDelete={this.handleDelete}
/>
</>
);
}
}
export default Parent;
FirstChild.js
import React from "react";
class FirstChild extends React.Component {
render() {
return (
<>
{this.props.Data.slice(0, 5).map((el) => {
return <h1 key={el._id}>{el._id}</h1>;
})}
</>
);
}
}
export default FirstChild;
SecondChild.js
import React, { useState } from "react";
const SecondChild = ({ handleUpdate, handleDelete }) => {
const [idToDelete, setIdToDelete] = useState(null);
const [newID, setNewID] = useState(null);
const [newTitle, setNewTitle] = useState("");
return (
<>
<input
name="_id"
type="number"
onChange={(e) => setIdToDelete(e.target.value)}
placeholder="Which object you want to delete"
/>
<button type="submit" onClick={() => handleDelete(idToDelete)}>
Delete
</button>
<br></br>
<br></br>
<br></br>
<input
type="text"
name="_id"
placeholder="id"
onChange={(e) => setNewID(e.target.value)}
/>
<input
type="text"
name="title"
placeholder="title"
onChange={(e) => setNewTitle(e.target.value)}
/>
<button
type="submit"
onClick={() => handleUpdate({ _id: newID, title: newTitle })}
>
Update
</button>
</>
);
};
export default SecondChild;

React ToDoList Project - Unique IDs

I am trying to introduce unique identifiers for list items instead of using the index but every method I try, I can't seem to get it working in the child. This is the base I am working with. I did install and imported import { v4 as uuidv4 } from 'uuid'; to make it a bit easier
All you have to do is simply put in 'uuidv4()' to generate a random ID
Parent
import React from 'react';
import './App.css';
import ShoppingCartList from './ShoppingCartList'
import { v4 as uuidv4 } from 'uuid';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
shoppingCart: [],
newItem: '',
errorMessage: 'false',
};
this.onRemoveItem = this.onRemoveItem.bind(this);
}
handleChange = (e) => {
this.setState ({ newItem: e.target.value})
}
handleClickAdd = (e) => {
if(this.state.newItem === '') {
this.setState({errorMessage: 'true'});
} else {
return ( this.setState({ shoppingCart: this.state.shoppingCart.concat(this.state.newItem) }),
this.setState({newItem: ''}),
this.setState({errorMessage: 'false'})
)}
}
handleSubmit = (e) => {
e.preventDefault()
}
onRemoveItem = (i) => {
this.setState(state => {
const shoppingCart = state.shoppingCart.filter((item, j) => i !== j);
return {shoppingCart}
})}
render() {
return (
<div>
<form onSubmit ={this.handleSubmit}>
Shopping Cart Items
<br></br>
{ this.state.errorMessage === 'true' &&
<p className='error'> Please enter an item </p> }
<ul>
{this.state.shoppingCart.map((item, index,) => {
return <ShoppingCartList
item={item}
index={index}
onRemoveItem={this.onRemoveItem}
/>
})}
</ul>
<input
placeholder='Enter your item here'
value={this.state.newItem}
onChange={this.handleChange}
></input>
<button type='submit' onClick={this.handleClickAdd}>Add to Shopping list</button>
</form>
</div>
)
}
}
export default App;
Child
[code]
import React from 'react';
function ShoppingCartList ({item,index, onRemoveItem}) {
return (
<li key={item}>{item} <button type="button" onClick={() => onRemoveItem(index)}>Delete</button></li>
)
}
export default ShoppingCartList;
Issues
React keys should be defined on the element/component being mapped, inside the child component is the wrong location
Solution
When adding items to the shopping cart, generate the unique id when adding to state.
Use the item id as the react key in the parent when mapping the cart
items, and as a way to identify the item to be removed from the cart.
Update handleClickAdd to create a new item object with id and value. Spread the existing cart array into a new array and append the new item object to the end.
handleClickAdd = (e) => {
if (this.state.newItem === "") {
this.setState({ errorMessage: true });
} else {
this.setState((prevState) => ({
shoppingCart: [
...prevState.shoppingCart,
{
id: uuidv4(), // <-- new unique id
value: prevState.newItem // <-- item value
}
],
newItem: "",
errorMessage: false
}));
}
};
Update onRemoveItem to take an id to filter by.
onRemoveItem = (id) => {
this.setState((prevState) => ({
shoppingCart: prevState.shoppingCart.filter((item) => item.id !== id)
}));
};
Update your render to add the react key to ShoppingCartList.
{this.state.shoppingCart.map((item) => {
return (
<ShoppingCartList
item={item}
key={item.id}
onRemoveItem={this.onRemoveItem}
/>
);
})}
Update ShoppingCartList to render the item value and pass the item id to the remove item callback.
const ShoppingCartList = ({ item, onRemoveItem }) => (
<li>
{item.value}{" "}
<button type="button" onClick={() => onRemoveItem(item.id)}>
Delete
</button>
</li>
);

input target value from child component

I've managed to get my input component to render onto the dom, however I'm having a bit of trouble accessing the props.
Functional input component
const InputField = props => {
const { inputValue, updateInputValue } = props
return (
<Input>
<input
type="text"
placeholder="Please specify"
value={inputValue}
onChange={updateInputValue}
/>
<hr />
<label>Other</label>
</Input>
)
}
The component is only rendered to the dom based on an object property inside of an array
const MultiChoiceQuestions = props => {
const { multiChoiceArray, handleClick } = props
return (
<ButtonContainer>
{multiChoiceArray.map(questionChoice => {
if (questionChoice.type === 'input') {
return <InputField />
}
return (
<Button type="button" key={questionChoice.id} onClick={() => handleClick(questionChoice)}>
{questionChoice.text}
</Button>
)
})}
</ButtonContainer>
)
}
The multiChoice component is imported once again to create a top-level component that the app consumes
const Question = props => {
let responses
switch (props.data.type) {
case 'multiChoice':
responses = (
<MultiChoiceQuestions
multiChoiceArray={props.data.choices}
handleClick={props.handleClick}
inputValue={props.inputValue}
updateInputValue={props.updateInputValue}
/>
)
break
default:
responses = <div>Error: no question type: `{props.data.type}`</div>
}
const { data } = props
return (
<AnimatedDiv key={data.id}>
<QuestionText>{data.text}</QuestionText>
{responses}
</AnimatedDiv>
)
}
And the final component looks like this
class Survey extends Component {
constructor(props) {
super(props)
this.state = {
currentQuestionId: 1,
userAnswers: [],
isActive: false,
inputValue: '',
}
this.selectAnswer = this.selectAnswer.bind(this)
this.test = this.test.bind(this)
}
selectAnswer = answer => {
this.setState(state => ({
currentQuestionId: state.currentQuestionId + 1,
userAnswers: state.userAnswers.concat([answer]),
isActive: !state.isActive,
}))
}
checkInput = event => {
this.setState({
inputValue: event.target.value,
})
}
test = event => {
console.log(event.target.value)
}
render() {
const { currentQuestionId, isActive, inputValue } = this.state
const { questions } = this.props
const currentPercentage = (currentQuestionId * 100) / questions.length
return (
<SurveyContainer>
<Question
data={questions.find(q => q.id === currentQuestionId)}
className={isActive ? 'active' : ''}
handleClick={this.selectAnswer}
value={inputValue}
onChange={this.test}
/>
</SurveyContainer>
)
}
}
The InputField component renders out just fine, however, the function for my onChange event is not firing...There's a mistake somewhere in the pipeline, probably inside the question component?
It looks like you haven't passed any props to <InputField /> in your MultiChoiceQuestions component.
I can not see where you pass props from
<MultiChoiceQuestions>
...
<InputFiled props={props} />
...
</MultiChoiceQuestions>
Probably pass only the props which are needed in InputField component, such as inputValue, updateInputValue:
<InputFiled
inputValue={inputValue}
updateInputValue={updateInputValue}
/>
const InputField = (inputValue, updateInputValue) => {
...
<input
type="text"
placeholder="Please specify"
value={inputValue}
onChange={(e) => updateInputValue(e)}
/>
...
}
Hope that will help.

Generating Search suggestions in React?

I am looking to generate search suggestions that match data collected, like so:
As you type in you get suggestions:
I am referencing some of the tutorial work from WesBos:
https://github.com/wesbos/JavaScript30/blob/master/06%20-%20Type%20Ahead/index-FINISHED.html
I've got the data logging in the console but now I am unsure how to get it to render. Below are my components (My thoughts were to generate the divs as a loop in App.js and pass the props to Match.js which I would eventually import but I am not sure if I am approaching this wrong):
App.js
import React, { Component } from 'react';
import { Form, Button } from 'react-bootstrap';
import 'bootstrap/dist/css/bootstrap.min.css';
const my_data = require('./data/test.json')
class App extends Component {
constructor(props) {
super(props);
this.state = {
links: [],
selectedLink:null,
userLocation: {},
searchInput: "",
showMatches: false,
matches: []
};
}
componentDidMount() {
fetch('https://data.cityofnewyork.us/resource/s4kf-3yrf.json')
.then(res=> res.json())
.then(res=>
//console.log(json)
this.setState({links:res})
);
}
render() {
const handleInputChange = (event) => {
event.preventDefault()
this.setState({searchInput: event.target.value })
//console.log(event.target.value)
}
const handleSubmit = (event) => {
event.preventDefault()
const data = this.state
displayMatches();
}
const findMatches = (wordToMatch, my_obj) => {
return my_obj.filter(place => {
// here we need to figure out the matches
const regex = new RegExp(wordToMatch, 'gi');
//console.log(place.street_address.match(regex))
return place.street_address.match(regex)
});
}
const displayMatches =() => {
const matchArray = findMatches(this.state.searchInput, this.state.links);
matchArray.map(place => {
console.log(place.street_address);
this.setState({matches:place})
this.setState({showMatches:true})
});
}
return (
<div>
<Form style = {{width: "75%"}} onSubmit = {handleSubmit}>
<Form.Group controlId="formSearch">
<Form.Control
type="text"
name = "my_search"
placeholder="Search for a Link Near you..."
onChange = {handleInputChange} />
</Form.Group>
<Button variant="primary" type="submit">
Search
</Button>
</Form>
<div>
{`How can I generate the console logged values as dynammic suggestions?`}
</div>
</div>
);
}
}
export default App;
Match.js
import React from 'react';
const match = ( props ) => {
return (
<div className="Matches">
<p>{`data is passed: ${props.address}`}</p>
</div>
)
};
export default match;
Appreciate the help.
Answers - Using Suggestions below
App.js
import React, { Component } from 'react';
import { Form, Button, ListGroup } from 'react-bootstrap';
import 'bootstrap/dist/css/bootstrap.min.css';
import Match from './Match'
const my_data = require('./data/test.json')
class App extends Component {
state = {
links: [],
selectedLink:null,
userLocation: {},
searchInput: "",
showMatches: false,
matches: [],
searchLink:[]
}
componentDidMount() {
fetch('https://data.cityofnewyork.us/resource/s4kf-3yrf.json')
.then(res=> res.json())
.then(res=>
//console.log(json)
this.setState({links:res})
);
}
handleInputChange = (event) => {
event.preventDefault()
this.setState({searchInput: event.target.value })
console.log(event.target.value)
}
handleSubmit = (event) => {
event.preventDefault()
this.displayMatches();
}
findMatches = (wordToMatch, my_obj) => {
return my_obj.filter(place => {
// here we need to figure out the matches
const regex = new RegExp(wordToMatch, 'gi');
//console.log(place.street_address.match(regex))
return place.street_address.match(regex)
});
}
displayMatches =() => {
const matchArray = this.findMatches(this.state.searchInput, this.state.links);
const newStateMatches = matchArray.map(place => {
console.log(place.street_address);
return place
});
this.setState({matches:newStateMatches})
this.setState({showMatches:true})
}
alertClicked =(event) => {
//alert('you clicked an item in the group')
const data = event.target
console.log('clicked this data:', data)
this.setState({searchLink: event.target})
console.log(this.state.searchLink)
}
render() {
return (
<div>
<input
placeholder="Search for a Link Near you..."
onChange = {this.handleInputChange}
value = {this.state.searchInput}
/>
<Button onClick={this.handleSubmit}>
Search
</Button>
<ListGroup defaultActiveKey="#link1">
{
this.state.matches.map(match => {
return <Match
address={match.street_address}
alertClicked={this.alertClicked}/>
})
}
</ListGroup>
</div>
);
}
}
export default App;
Match.js
import React from 'react';
import { ListGroup } from 'react-bootstrap';
const match = ( props ) => {
return (
<ListGroup.Item
className="Matches"
action onClick={props.alertClicked}>
<p>{`${props.address}`}</p>
</ListGroup.Item>
)
};
export default match;
I think your initial instinct as to how to do this is correct :
get the matches
store them in state
map over the state and render one component per match, passing the relevant data as props
To answer your question exactly, mapping over state to render component usually looks something like this :
<div>
{
matches.map(match => {
return <Match address={match.address} name={match.name} />
})
}
</div>
You can also destructure properties like this :
<div>
{
matches.map(({address, name}) => {
return <Match address={address} name={name} />
})
}
</div>
Also, another minor observation: you notice I called the component Match with a capital M. It is a convention in React and other component based libraries that components' names are always capitalized, not only in the file name but also in the code.
First move all your method definitions outside of your render function (you'll need to update const and add this.
in your display matches you should be building a newstate array then setState with the new array once built
i do not use react bootstrap but it did not appear that your submit button was within the form therefor was not submitting the form.
Make sure react components are capitalized (match component should be Match)
I passed the whole 'place' down to the Match component via place prop:
<Match place={place} />
if you want to access the address like you did you would need to pass each individual value from the place down to the Match component like:
<Match address={place.address} />
(also if you are only initializing state before first render you can do so outside of the constructor)
I simplified the return statement to just use a plain input and button tag for simplicity but you can probably get going from here
Working Snippet:
const Match = ( props ) => {
return (
<div className="Matches">
<p>{`data is passed: ${props.place.street_address}`}</p>
</div>
)
};
class SomeComponent extends React.Component{
state = {
links: [],
selectedLink:null,
userLocation: {},
searchInput: "",
showMatches: false,
matches: []
}
componentDidMount() {
fetch('https://data.cityofnewyork.us/resource/s4kf-3yrf.json')
.then(res=> res.json())
.then(res=>
//console.log(json)
this.setState({links:res})
);
}
handleInputChange = (event) => {
event.preventDefault()
this.setState({searchInput: event.target.value })
//console.log(event.target.value)
}
handleSubmit = (event) => {
event.preventDefault()
this.displayMatches();
}
findMatches = (wordToMatch, my_obj) => {
return my_obj.filter(place => {
// here we need to figure out the matches
const regex = new RegExp(wordToMatch, 'gi');
//console.log(place.street_address.match(regex))
return place.street_address.match(regex)
});
}
displayMatches =() => {
const matchArray = this.findMatches(this.state.searchInput, this.state.links);
const newStateMatches = matchArray.map(place => {
console.log(place.street_address);
return place
});
this.setState({matches:newStateMatches})
this.setState({showMatches:true})
}
render() {
return (
<div>
<input
placeholder="Search for a Link Near you..."
onChange = {this.handleInputChange}
value = {this.state.searchInput}
/>
<button onClick={this.handleSubmit}>
Search
</button>
{this.state.matches.map((place)=>{
return <Match place={place} />
})}
</div>
);
}
}
ReactDOM.render(
<SomeComponent />,
document.getElementById("react")
);
<div id='react'></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

How to Update This Reactjs Select

I have this wrapper class that is used because I am using Formik and the FieldArray
import React, { Component } from "react";
import { ReactDOM } from "react-dom";
import Select from "react-select";
import { observer } from "mobx-react";
import { axiosInstance } from "../stores/AxiosInstance";
#observer
export default class CountryStateSelectComponent extends React.Component {
constructor(props) {
super(props);
this.state = { stateOptions: [] };
}
handleCountryChange = value => {
const that = this;
axiosInstance
.get(`/States?countryId=${value.value}`)
.then(function(response) {
that.props.onChange(that.props.countryName, value);
that.props.onChange(that.props.stateName, null);
const states = response.data.map(state => {
return { label: state.name, value: state.id };
});
// if I move out state select code then won't need to update state here but don't know how to call something like updateState(record)
that.setState({
stateOptions: states
});
});
};
handleStateChange = value => {
console.log(this.props.stateName, value)
this.props.onChange(this.props.stateName, value);
};
handleCountryBlur = () => {
this.props.onBlur(this.props.countryName, true);
};
handleStateBlur = () => {
this.props.onChange(this.props.stateName, true);
};
render() {
const props = this.props;
return (
<React.Fragment>
<div className="field">
<label className="label">Country</label>
<div className="control">
<Select
options={props.options}
isMulti={props.isMulti}
onChange={this.handleCountryChange}
onBlur={this.handleCountryBlur}
closeMenuOnSelect={props.closeMenuOnSelect}
/>
{this.props.CountryError}
</div>
</div>
<div className="field">
<label className="label">State/Province</label>
<div className="control">
<Select
options={this.state.stateOptions}
onChange={this.handleStateChange}
onBlur={this.handleStateBlur}
/>
{this.props.StateError}
</div>
</div>
</React.Fragment>
);
}
}
However what I found is that when the State gets selected the value does not get stored in Formik(it gets stored as undefined and sometimes true).
So now I am thinking maybe moving out the State Zip out and making it's own wrapper or something but I don't know how to get the "states" that came back and populate the correct state box as they can generate many.
#inject("AccountSetupStore")
#observer
export default class MyComponent extends Component {
constructor(props) {
super(props);
this.state = { records: [this.generateRecord(1, true, true)] };
}
componentDidMount() {
const accountSetupStore = this.props.AccountSetupStore;
accountSetupStore.getCountries();
}
updateState(record) {
// would like to call this method that can somehow update the record
// propblem is I don't seem to have access to props when this function is being called from the CountryStateSelectComponent
}
render() {
const props = this.props;
const accountSetupStore = props.AccountSetupStore;
const countries = [];
for (const country of accountSetupStore.countries) {
countries.push({ value: country.id, label: country.name });
}
return (
<section className="accordions">
<Formik
initialValues={{
records: this.state.records
}}
onSubmit={(
values,
{ setSubmitting, setErrors}
) => {
console.log(values,"values");
}}
validationSchema={Yup.object().shape({
branches: Yup.array()
.of(
Yup.object().shape({
})
)
})}
render={({
values,
setFieldValue,
setFieldTouched,
}) => (
<FieldArray
name="records"
render={arrayHelpers => (
<Form>
{values.records.map((record, index) => {
return (<article}>
<CountryStateSelectComponent options={countries}
onChange={setFieldValue}
countryName={`records[${index}].selectedCountry`}
stateName={`records[0].selectedState`}
onBlur={setFieldTouched}
isMulti={false}
index = {index}
closeMenuOnSelect={true}
CountryError = {<ErrorMessage name={`records[${index}].selectedCountry`}/>}
StateError= {<ErrorMessage name={`records[${index}].selectedState`}/>}
/>
</article>)
})}
</Form>
)}
/>
)}
/>
</section>
);
}
}
React Select onChange sends the value to the method supplied
const onStateChange = (selectedOption, {action}) => {
//do something with the selectedOption according to the action
}
<Select onChange={onStateChange} />
See the documentation for the onChange in the Props documentation.

Categories

Resources