Manage many inputs between sibling components in React - best approach? - javascript

I am new to this topic.
In the parent component App I have two siblings : SideMenu and Document
The idea is that the user inputs values (SideMenu) which will be renedered on the Document. There will be more than 20 inputs. Since this is the first time I do this sort of state management, what are the best or maybe easiest approaches for this attempt of project.
function App() {
const [fullName, setFullName] = useState("")
const [address, setAddress] = useState("")
return (
<div className='app'>
<SideMenu />
<Document />
</div>
)
}
export default App
const SideBar = () => {
return (
<div>
<div className='input-group'>
<label>Full Name:</label>
<input type='text' />
</div>
<div className='input-group'>
<label>Address:</label>
<input type='text' />
</div>
</div>
)
}
const Document = () => {
return (
<div>
<h1>{fullName}</h1>
<p>{address}</p>
</div>
)
}

You can create an object for your form and store the form inputs in this object. Shared state can be stored in the most closest and common component (in your situation this is your parent component) according to your child components. [1]
When you make an update from a child component other child component that is sharing state will be syncronized and your state will be updated. You shouldn't use redux like state management tools unless you are need to set a global state.
I have made a revision for your example, this scenario allows you to pass the state in the parent component to the child components and update the state in the parent component from the child components.
I used a common event handler in the parent component, this functions captures the html event and we parse this event and update the state via this function. [2][3]
import "./styles.css";
import { useState } from "react";
import SideBar from "./SideBar";
import Document from "./Document";
export default function App() {
const [values, setValues] = useState({
fullName: "",
address: "",
postalCode: ""
});
function handleChange(event) {
setValues({ ...values, [event.target.name]: event.target.value });
}
return (
<div className="app">
<SideBar values={values} setValues={handleChange} />
<Document values={values} setValues={handleChange} />
</div>
);
}
export default function Document({ values }) {
return (
<div>
<h1>Document</h1>
<p>Full Name: {values.fullName}</p>
<p>Address: {values.address}</p>
<p>Postal Code: {values.postalCode}</p>
</div>
);
}
export default function Sidebar({ setValues }) {
return (
<div>
<div className="input-group">
<label>Full Name:</label>
<input type="text" name="fullName" onChange={setValues} />
</div>
<div className="input-group">
<label>Address:</label>
<input type="text" name="address" onChange={setValues} />
</div>
<div className="input-group">
<label>Address:</label>
<input type="text" name="postalCode" onChange={setValues} />
</div>
</div>
);
}
Code Sandbox Link: https://codesandbox.io/s/stackoverflow-74961591-wpmcnd
[1]: Passing Props to a component: https://beta.reactjs.org/learn/passing-props-to-a-component
[2]: Updating Objects in State: https://beta.reactjs.org/learn/updating-objects-in-state
[3]: HTML Change Event: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event

The default, go-to solution would be to use a container component that controls your form inputs state (this would be App in your case). Just pass the values and setters down one level by props and everything should be ok, simple and predictable.
If things start to get complicated then libraries such as Formik or react-hook-form help a lot. When it comes to managing multiple or complex forms that may also need validation they are your best bet. I suggest you take this approach.
Using Redux for this kind of situation is a huge anti-pattern. Redux global store should be only used for global state, not local form state.
Context API is well suited when you need to pass data to multiple deeply nested children. This way you do not need to pass props dozens of levels down the tree. However, it is usually used by 3rd party libraries such as the ones mentioned above (all of them).

You can use Formik library for handling many inputs. Wrap both components inside Formik and use formik's methods.
import { Formik } from 'formik';
<Formik
initialValues={{ fullName: '', address: '' }}
onSubmit={(values) => {
alert(JSON.stringify(values, null, 2));
}}
>
{({handleChange, values, handleSubmit}) => (
<form onSubmit={handleSubmit}>
<div className='app'>
<SideMenu
handleChange={handleChange}
/>
<Document values={values} />
<button type="submit">Submit</button>
</form>
)}
</Formik>
You dont need to create multiple states for each input. handlChange will handle itself. You just need add name or id attribute to input. Also you can access values of each input using the values parameter like values.fullName.
const SideBar = ({handleChange}) => {
return (
<div>
<div className='input-group'>
<label>Full Name:</label>
<input
type='text'
onChange={handleChange}
name="fullName"
/>
</div>
<div className='input-group'>
<label>Address:</label>
<input
type='text'
onChange={handleChange}
name="address"
/>
</div>
</div>
)
}
const Document = ({values}) => {
return (
<div>
<h1>{values.fullName}</h1>
<p>{values.address}</p>
</div>
)
}

Related

Extracting and reuse React components

In a React app I have a couple of working components like this one:
<div className="form-group col-md-6">
<label className='inp-lbl'>{utl.nameWord()}</label>
<div className='inp-name'>
<input
type="text"
ref="name"
defaultValue={this.name}
onChange={e => {
this.setState((state) => {
return {name: e.target.value};
});
}}
/>
</div>
</div>
Instead of repeating similar code for each or them, I want to extract a generic component that I will be able to reuse; but it does not work as I expect. Here is the new component I made:
class InputField extends React.Component {
constructor(props) {
super(props);
this.state = {
labelStr: props.lbStr,
nameStr: props.nmStr,
defltVal: props.dfVl,
onChgFnc: props.onChFn
};
// this.onChgFnc = props.onChFn
}
render() {
return (
<React.Fragment>
<div className="form-group col-md-6">
<label className='inp-lbl'>{this.state.labelStr}</label>
<div className='inp-name'>
<input
type="text"
ref={this.state.nameStr}
defaultValue={this.state.defltVal}
onChange={this.state.onChgFnc}
/>
</div>
</div>
</React.Fragment>
)
}
}
And this is how I call the new component:
<InputField lbStr={utl.nameWord()} nmStr='name'
dfVl={this.name}
onChFn={handleChange} />
The function handleChange is defined as:
function handleChange(event) {
this.setState((state) => {
return {name: event.target.value};
})
}
Though I thought this should work, it does not. So it would be great if somebody could spot the mistake I am making and let me know.
You could be suffering from an incorrectly bound this inside your handleChange function. Perhaps try just closing over the setState call instead of referencing it via this. For example
function handleChange(event) {
setState({ name: event.target.value })
}
(I've also changed the particular usage of the state-setter to accept a value as you weren't using the previous state value)
I would also go one further and change to a functional component and don't store your props in state as this will disconnected the component from the flow of prop values if/when they change.
function InputField({ name, label, onChange, defaultValue }){
return (
<div className="form-group col-md-6">
<label className='inp-lbl'>{label}</label>
<div className='inp-name'>
<input
type="text"
ref={name}
defaultValue={defaultValue}
onChange={onChange}
/>
</div>
</div>
)
}
I don’t understand why you need to assign the onChangehandler from props to state object in Child Component. You can directly bind the change handler from props’ change callback function.
<input type="text"
ref={this.state.nameStr}
defaultValue={this.state.defltVal}
onChange={this.props.onChFn} />
Storing props in state is an anti-pattern in React as it often leads to problem of multiple sources of truth(same info) in a component.
A better way to write your component would be to initialize the value of field from props and derive rest of the values directly from props.
You can directly bind the change handler from props’ change callback function.
class InputField extends React.Component {
constructor(props) {
super(props);
this.state = {
nameStr: props.nmStr,
};
}
render() {
return (
<React.Fragment>
<div className="form-group col-md-6">
<label className='inp-lbl'>{props.lbStr}</label>
<div className='inp-name'>
<input
type="text"
value={this.state.nameStr}
defaultValue={this.props.defltVal}
onChange={this.props.onChgFnc}
/>
</div>
</div>
</React.Fragment>
)
}
}

Is there a way to get a React component's internal values when I click a button on the parent?

Suppose I have a component like this -
const MyForm = ({ formId }) => (
<div>
<input type="text" placeholder="Full name"></input>
<input type="text" placeholder="Email"></input>
</div>
)
export default MyForm;
And then I have my App.js like so -
import React from "react";
import MyForm from "./MyForm";
const App = () => (
<div id="app">
<MyForm formId="formOne"></MyForm>
<MyForm formId="formTwo"></MyForm>
<button onClick={
() => {
// Here, when the user clicks the button,
// I want to get values of both the textboxes,
// from both the component instances
}
}>Submit</button>
</div>
)
export default App;
So basically, what I want is - when the button is clicked, I want to be able to retrieve the values of the textboxes. One way to do this is to raise an event from inside MyForm.js so that every text change is bubbled up to the parent via a callback function prop, but that feels too cumbersome, especially if the form has a lot of fields. Is there any simple or direct way to do this? Do I need to involve global state management tools like Redux?
State inside a component is specific only to that component, the parent , children or sibling of a component have no idea of the state. The only way to communicate the value from one component to another component is via props . In your case, what we need is a state to reside at the App which can then be passed as a prop to both the MyForm Components.
App.js
const [ formState, setFormState ] = useState({ formOne: {fullName: '', Email: ''}, formTwo: '' })
const updateFormValues = (formId, key, value) => {
const stateCopy = JSON.parse(JSON.stringify(formState));
const formToUpdate = stateCopy[formId];
formToUpdate[key] = value;
setFormState(stateCopy)
}
<MyForm formId="formOne" values={formState.formOne} updateFormValues={updateFormValues}></MyForm>
<MyForm formId="formTwo" values={formState.formTwo} updateFormValues={updateFormValues}></MyForm>
MyForm.js
const MyForm = ({ formId, values, updateFormValues }) => {
const onInputChange = (e, key) => {
updateFormValues(formId, key, e.target.value)
}
return(
<div>
<input type="text" onChange={(e) => onInputChange(e, 'fullName'} value={values.fullName} placeholder="Full name"></input>
<input type="text" onChange={(e) => onInputChange(e, 'email'} value={values.email} placeholder="Email"></input>
</div>
)}
export default MyForm;
To have access to data inside children components you need to lift the state to the parent component.
One-way data flow
Identify every component that renders something based on that state.
Find a common owner component (a single component above all the components that need the state in the hierarchy).
Either the common owner or another component higher up in the hierarchy should own the state.
If you can’t find a component where it makes sense to own the state, create a new component solely for holding the state and add it somewhere in the hierarchy above the common owner component.
One way to do this:
import React, { useState } from "react";
function MyForm(props) {
const { handleChange, values } = props;
return (
<div>
<label htmlFor="name">Your name</label>
<input
type="text"
placeholder="Full name"
onChange={handleChange}
value={values.name}
id="name"
name="name"
/>
<label htmlFor="email">Your email</label>
<input
type="email"
placeholder="Email"
onChange={handleChange}
value={values.email}
id="email"
name="email"
/>
</div>
);
}
function App() {
const [values, setValues] = useState({ name: "", email: "" });
const handleChange = (event) => {
const updatedForm = { ...values, [event.target.name]: event.target.value };
setValues(updatedForm);
};
return (
<div id="app">
<MyForm
formId="formOne"
values={values}
handleChange={handleChange}
></MyForm>
<button
onClick={() => {
console.log(values);
}}
>
Submit
</button>
</div>
);
}
export default App;

Using react HOC with a form. Passing common JSX and state down using a HOC

I just finished up a pretty big project that uses a form in different parts of a react app. The form is identical throughout however the functionality is different depending on where the form is being used.
So right now I have multiple Components with duplicate forms. All of these forms are controlled i.e (use this.state... for the value) the only difference is the render methods and what happens to the form data on certain button events.
I realize this is horrible coding and really want to use a HOC to make these components way more flexible and cleaner.
this is one of the forms, There are 2 more similar to this.
sampleForm = (
<form action="" name="sample">
<div className="group">
<label htmlFor="">Descriptive Name:</label>
<input type="text" name="name" value={this.state.name}
onChange={this.handleChange} placeholder="Descriptive Name" />
</div>
<div className="group">
<label>Sample Codename:</label>
<input type="text" name="codeName" value={this.state.codeName}
onChange={this.handleChange} placeholder="Ex: MM_MG_01" />
</div>
<div className="group">
<label htmlFor="">GPS Coordinates:</label>
<input type="text" name="coords" value={this.state.coords}
onChange={this.handleChange} placeholder="GPS Coordinates" />
</div>
<div className="group">
<label htmlFor="">Metagenomic Data:</label>
<textarea type="text" name="METAdesc" value=
{this.state.METAdesc}
onChange={this.handleChange} placeholder="Image Description" rows={7} />
<input type="file" name="METAimage"
onChange={this.handleChange} />
</div>
{notes}
</form>
)
I currently have these three duplicated in the render method ( four times :/ )
How can I pass these three down to components?
A Higher Ordered Component is a React pattern where:
a function takes a Component and returns a new Component.
https://reactjs.org/docs/higher-order-components.html
One thing an HOC can do for a Form is to manage state, handling Events such as onChange and onSubmit, etc, etc. As such, consider a Form Component as a functional component that is passed as a parameter to your FormHandler HOC.
For instance,
In FormHandler.js
const withFormHandling = FormComponent => class extends Component {/* Component Logic */}
export default withFormHandling
In Form.js
import withFormHandling from './path/to/Components/FormHandler'
const Form = props => {/* Component Logic */}
export default withFormHanlding(Form);
How then do we handle form specifics, props and state for multiple different forms?
Identify the state or props that every form should have
In your case, perhaps the following:
formAction
formName
handleChange
handleSubmit
inputNames
notes
errors
I would consider passing in inputNames and errors as props (they should match in structure). You can add all sorts of complexity here or keep it simple. Personally, I keep in my state a fields object and an errors object, both with matching keys. One for maintaining user-entered values, the other for storing the results of field validation.
Let's then fill out our HOC
const withFormHandling = FormComponent => class extends Component {
constructor(props) {
super(props)
this.state = {
fields: {...props.inputNames},
errors: {...props.errors},
selectedFile: null
}
this.handleChange = this.handleChange.bind(this);
this.handleFile = this.handleFile.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
// https://codeburst.io/save-the-zombies-how-to-add-state-and-lifecycle-methods-to-stateless-react-components-1a996513866d
static get name() {
return Component.name;
}
handleChange(e) {
const target = e.target;
let value = target.type === 'checkbox' ? target.checked : target.value;
let name = target.name;
const fields = {...this.state.fields}, errors = {...this.state.errors};
const error = //create a validation function that returns an error based on field name and value
fields[name] = value;
errors[name] = error;
this.setState({ fields, errors })
}
handleFile(e) {
this.setState({selectedFile: event.target.files[0]})
}
handleSubmit(e) {
//validate form
//flatten fields into structure of data for form submission
//handle submission of data and also file data
}
render() {
return <FormComponent
{...this.props} //to access form specific props not handled by state
fields={this.state.fields}
errors={this.state.errors}
handleChange={this.handleChange}
handleFile={this.handleFile}
handleSubmit={this.handleSubmit}
/>
}
}
export default withFormHandling
This Pattern works because the render function of the returned Component renders the Form Component passed as a parameter to the HOC function.
So, you can create any number of Forms with this HOC as the handler. You can consider passing into the HOC a tree representing the input structure of the form to make this even more modular and reusable.
For now, let's fill out Form.js for the example you provided:
import withFormHandling from './path/to/Components/FormHandler'
const Form = ({formAction, formName, handleChange, handleFile, handleSubmit, fields, errors, notes}) => {
return (
<form action={formAction} name={formName} onSubmit={handleSubmit}>
<div className="group">
<label htmlFor="name">Descriptive Name:</label>
<input type="text" name="name" value={fields.name}
onChange={handleChange} placeholder="Descriptive Name" />
</div>
<div className="group">
<label htmlFor="codeName">Sample Codename:</label>
<input type="text" name="codeName" value={fields.codeName}
onChange={handleChange} placeholder="Ex: MM_MG_01" />
</div>
<div className="group">
<label htmlFor="coords">GPS Coordinates:</label>
<input type="text" name="coords" value={fields.coords}
onChange={handleChange} placeholder="GPS Coordinates" />
</div>
<div className="group">
<label htmlFor="METAdesc">Metagenomic Data:</label>
<textarea type="text" name="METAdesc" value=
{fields.METAdesc}
onChange={handleChange} placeholder="Image Description" rows={7} />
<input type="file" name="METAimage"
onChange={handleFile} />
</div>
{notes}
</form>
)
}
export default withFormHanlding(Form);
Finally, in some other Component, you call the Form Component as often as you like, passing in unique props.
//...some other Component Render Method
// form one, with its own internal state managed by HOC
<Form formAction={'https://someendpoint1'} formName={"some form 1"} inputNames={{name:'', codename:''}} errors={{name:'', codename:''}} notes={"some notes 1"}/>
// form two, with its own internal state managed by HOC
<Form formAction={'https://someendpoint2'} formName={"some form 2"} inputNames={{name:'', codename:''}} errors={{name:'', codename:''}} notes={"some notes 2"}/>
// form three, with its own internal state managed by HOC
<Form formAction={'https://someendpoint3'} formName={"some form 3"} inputNames={{name:'', codename:''}} errors={{name:'', codename:''}} notes={"some notes 3"}/>
This is how I have handled an app with many different forms that have a similar structure.
Another pattern to consider is render props, but I'll leave that up to another question and another respondent.

Update functionality in react

I am newbie to React and I am trying to do update on react. I don't get the exact logic to make it and hence I need your help.
On click of update, I managed to get the values of selected contact but later on, i don't get how to populate those value onto input text boxes and again on submit after change of values, update the selected contact. I came across onChange but I don't understand.
Clues i knew:
this.refs.name.value and this.refs.number.value are values which are in input textbox . And on update, we need to set these value into the state on that corresponding index.
My code and screenshot is below:
Person.js - number is taken as the key , considering individual number is unique
editcontact(id){
this.props.onChange(id);
}
render() {
return(
<div className="panel panel-default">
<div className="panel-heading">
<h4>{this.props.detail.name} </h4>
<a className="b" href="#" onClick={this.deletecontact.bind(this,this.props.detail.number)}> Delete </a>
<a className="b" href="#" onClick={this.editcontact.bind(this,this.props.detail.number)}> Update </a>
</div>
<h6 className="panel-body">{this.props.detail.number}</h6>
</div>
</div>
)
}
It is passed to Contact.js
editcontact(id)
{
this.props.onChange(id);
}
render() {
var details;
if(this.props.data){
details=this.props.data.map(dts=>{
return(
<Person key={dts.number} detail={dts} onChange={this.editcontact.bind(this)} onDelete={this.deletecontact.bind(this)}></Person>
)
})
}
Then comes App.js
handleEdit(id){
console.log(id);
let cts=this.state.contacts;
let index=cts.findIndex( x => x.number === id);
console.log(cts[index]);
this.setState({ selectedContact: cts[index]; });
}
render() {
return (
<div className="App">
<div className="page-header">
<h2>Contact list</h2>
</div>
<AddContact newOne={this.state.selectedContact} addcontact={this.handleAddition.bind(this)}></AddContact>
<Contact onChange={this.handleEdit.bind(this)} onDelete={this.handleDelete.bind(this)} data={this.state.contacts}> </Contact>
</div>
);
}
AddContact.js
constructor(){
super();
this.state={
newContact:{
name:'',
number:''
}
}
}
addcontact(e){
// console.log(this.refs.name.value);\
e.preventDefault();
this.setState({
newContact:{
name: this.refs.name.value,
number:this.refs.number.value
}
},function(){
console.log(this.state.newContact);
this.props.addcontact(this.state.newContact);
})
this.refs.name.value="";
this.refs.number.value="";
}
render() {
console.log(this.props.newOne);
return (
<div className="col-md-6">
<form onSubmit={this.addcontact.bind(this)}>
<div className="form-group">
<label>Name </label>
<input className="form-control" type="text" ref="name" />
</div>
<div className="form-group">
<label>Number</label>
<input className="form-control" type="number" ref="number" />
</div>
<input type="submit" value="Submit"/>
</form>
</div>
);
}
}
what you need is to tell your component that you have a new state and you want it to re-render.
handleEdit(id){
console.log(id);
let cts=this.state.contacts;
let index=cts.findIndex( x => x.number === id);
this.setState({ selectedContact: cts[index]; });
}
render() {
return (
<div className="App">
<div className="page-header">
<h2>Contact list</h2>
</div>
<AddContact addcontact={this.handleAddition.bind(this)}></AddContact>
<Contact onChange={this.handleEdit.bind(this)} onDelete={this.handleDelete.bind(this)} data={this.state.contacts}> </Contact>
</div>
);
with the setState function you updating the state of this compoent and also make it to re-render. now you can decide what you want to do with this data: this.state.selectedContact like passing it to AddContact
Don't use .bind(this... there is no reason to do it. Use attribute={() => this.functionName()}
Don't use different naming, use some pattern for attributes names. e.g. addcontact should be addContact
Don't use so long lines. Use Eslint to show you all of such tips.
It's really hard to read your code now, make it more readable and you will have better time editing it yourself.
And now to have update, i would suggest using pure functional component to display things and higher order component to manage state of data.
(props) => <form> .... <input value={props.email} /> ... </form;
and in parent component, which is responsible for all data management add state. In state you can save values and pass it into child components using props.
When you will advance in React, you will start using extra libraries to manage state of the app, e.g. Redux. It makes similar thing, but all app's state is in one place and then you can access it from any part of the app. E.g. you show these inputs, then jump to another state of app to add some other thing and then you can easily jump back to this state and still have input's values that are partly entered.
Just save values in state. No matter how you manage your app's state and push values to display components using props. Google, read, check some videos on Youtube and you will get it.
https://facebook.github.io/react/docs/thinking-in-react.html

How to force remounting on React components?

Lets say I have a view component that has a conditional render:
render(){
if (this.state.employed) {
return (
<div>
<MyInput ref="job-title" name="job-title" />
</div>
);
} else {
return (
<div>
<MyInput ref="unemployment-reason" name="unemployment-reason" />
<MyInput ref="unemployment-duration" name="unemployment-duration" />
</div>
);
}
}
MyInput looks something like this:
class MyInput extends React.Component {
...
render(){
return (
<div>
<input name={this.props.name}
ref="input"
type="text"
value={this.props.value || null}
onBlur={this.handleBlur.bind(this)}
onChange={this.handleTyping.bind(this)} />
</div>
);
}
}
Lets say employed is true. Whenever I switch it to false and the other view renders, only unemployment-duration is re-initialized. Also unemployment-reason gets prefilled with the value from job-title (if a value was given before the condition changed).
If I change the markup in the second rendering routine to something like this:
render(){
if (this.state.employed) {
return (
<div>
<MyInput ref="job-title" name="job-title" />
</div>
);
} else {
return (
<div>
<span>Diff me!</span>
<MyInput ref="unemployment-reason" name="unemployment-reason" />
<MyInput ref="unemployment-duration" name="unemployment-duration" />
</div>
);
}
}
It seems like everything works fine. Looks like React just fails to diff 'job-title' and 'unemployment-reason'.
Please tell me what I'm doing wrong...
Change the key of the component.
<Component key="1" />
<Component key="2" />
Component will be unmounted and a new instance of Component will be mounted since the key has changed.
Documented on You Probably Don't Need Derived State:
When a key changes, React will create a new component instance rather than update the current one. Keys are usually used for dynamic lists but are also useful here.
What's probably happening is that React thinks that only one MyInput (unemployment-duration) is added between the renders. As such, the job-title never gets replaced with the unemployment-reason, which is also why the predefined values are swapped.
When React does the diff, it will determine which components are new and which are old based on their key property. If no such key is provided in the code, it will generate its own.
The reason why the last code snippet you provide works is because React essentially needs to change the hierarchy of all elements under the parent div and I believe that would trigger a re-render of all children (which is why it works). Had you added the span to the bottom instead of the top, the hierarchy of the preceding elements wouldn't change, and those element's wouldn't re-render (and the problem would persist).
Here's what the official React documentation says:
The situation gets more complicated when the children are shuffled around (as in search results) or if new components are added onto the front of the list (as in streams). In these cases where the identity and state of each child must be maintained across render passes, you can uniquely identify each child by assigning it a key.
When React reconciles the keyed children, it will ensure that any child with key will be reordered (instead of clobbered) or destroyed (instead of reused).
You should be able to fix this by providing a unique key element yourself to either the parent div or to all MyInput elements.
For example:
render(){
if (this.state.employed) {
return (
<div key="employed">
<MyInput ref="job-title" name="job-title" />
</div>
);
} else {
return (
<div key="notEmployed">
<MyInput ref="unemployment-reason" name="unemployment-reason" />
<MyInput ref="unemployment-duration" name="unemployment-duration" />
</div>
);
}
}
OR
render(){
if (this.state.employed) {
return (
<div>
<MyInput key="title" ref="job-title" name="job-title" />
</div>
);
} else {
return (
<div>
<MyInput key="reason" ref="unemployment-reason" name="unemployment-reason" />
<MyInput key="duration" ref="unemployment-duration" name="unemployment-duration" />
</div>
);
}
}
Now, when React does the diff, it will see that the divs are different and will re-render it including all of its' children (1st example). In the 2nd example, the diff will be a success on job-title and unemployment-reason since they now have different keys.
You can of course use any keys you want, as long as they are unique.
Update August 2017
For a better insight into how keys work in React, I strongly recommend reading my answer to Understanding unique keys in React.js.
Update November 2017
This update should've been posted a while ago, but using string literals in ref is now deprecated. For example ref="job-title" should now instead be ref={(el) => this.jobTitleRef = el} (for example). See my answer to Deprecation warning using this.refs for more info.
Use setState in your view to change employed property of state. This is example of React render engine.
someFunctionWhichChangeParamEmployed(isEmployed) {
this.setState({
employed: isEmployed
});
}
getInitialState() {
return {
employed: true
}
},
render(){
if (this.state.employed) {
return (
<div>
<MyInput ref="job-title" name="job-title" />
</div>
);
} else {
return (
<div>
<span>Diff me!</span>
<MyInput ref="unemployment-reason" name="unemployment-reason" />
<MyInput ref="unemployment-duration" name="unemployment-duration" />
</div>
);
}
}
I'm working on Crud for my app. This is how I did it Got Reactstrap as my dependency.
import React, { useState, setState } from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import firebase from 'firebase';
// import { LifeCrud } from '../CRUD/Crud';
import { Row, Card, Col, Button } from 'reactstrap';
import InsuranceActionInput from '../CRUD/InsuranceActionInput';
const LifeActionCreate = () => {
let [newLifeActionLabel, setNewLifeActionLabel] = React.useState();
const onCreate = e => {
const db = firebase.firestore();
db.collection('actions').add({
label: newLifeActionLabel
});
alert('New Life Insurance Added');
setNewLifeActionLabel('');
};
return (
<Card style={{ padding: '15px' }}>
<form onSubmit={onCreate}>
<label>Name</label>
<input
value={newLifeActionLabel}
onChange={e => {
setNewLifeActionLabel(e.target.value);
}}
placeholder={'Name'}
/>
<Button onClick={onCreate}>Create</Button>
</form>
</Card>
);
};
Some React Hooks in there

Categories

Resources