Trigger onChange when setting State in componentDidMount? - javascript

I need to add some query paramaters to my url as a person checks off checkboxes.
I am using react router so I do something like this in my checkboxes on change event.
const stringified = queryString.stringify(parsed);
const path = `${this.props.location.pathname}?${stringified}`;
this.props.history.replace(path)
This does however seem to cause a re-render of the page(not sure if this should be happening, would prefer it not to do that so maybe I got to use something other than replace?).
I wanted to check on componentDidMount the url to see if the value is there. If it is there then I wanted to update the state of the checkbox.
#observable
isChecked = false;
#action
componentDidMount() {
const parsed = queryString.parse(this.props.location.search);
this.isChecked = parsed && parsed["param"] === this.props.option;
}
However I don't see the onChange being trigger.
Right now I have on change a function that takes the value and uses it to filter, so I need the function to run.
I could put that function in the componentDidMount but I wanted to make sure before I do that, there is nothing I am missing on why the change event is not be fired.

Try setting the state in the constructor() and incomponentDidUpdate().
When a URL parameter is added to the same route, the existing component is utilized (i.e. an update event) vs. a new one being created. As a result, you won't see a componentDidMount() event.
Another option/solution is to update the state of isChecked directly and push the history/url change.

If what you are trying to prevent is the page refresh use this built in function in your onSubmit event(if I understand your question correctly.)
event.preventDefault();
It stops the browser from auto-refreshing! Make sure to call event in your function though.
ie
onSubmit=(event)=>{
event.preventDefault();
//rest of code
}
If you are trying to filter, the es6 .filter method is useful for checkboxes. I personally used a select dropdown menu to filter the options and selectively show the ticked items in a ToDo List: "Done" "Active" "Completed" and used those states in my filter method.

Related

React, how can I submit updates to Input box when clicking outside the component

I am looking for a solution in which a user can enter text into an input, and when they click anywhere outside of the component, it submits, saves the value.
In my case I have a top level component which dynamically generates Text Input components.It passes in the properties including an UpdateValue function.
In these functional components I am using the ability to add an event listener to the document, and then I detect if the click comes from outside the component in question. Having done a lot of research on stackoverflow, this seems to be the agreed upon method.
useEffect(() => {
document.addEventListener('mousedown', handleClick);
return () => {
document.removeEventListener('mousedown',handleClick);
}
},[])
const handleClick = (e) => {
if(node.current.contains(e.target))
{
return;
}
updateValue()
}
I have this working, in that the function gets called when I click outside the component, however, the function invoked on the parent component no longer seems to have access to the state..they appear all empty. I can only guess that because we are using a generic javascript function initially, the call doesn't have access to react stack.
So, my question is, how can I make this work where I want a nested functional component that has an input, and when a user clicks off component, it runs the updateValue function which can then use some internal state data to properly update this in the DB.
FYI, I have a onchange() on the input, which updates the value in the parent component already.
So, UpdateValue() is a trigger to basically submit final changes to DB.
Your updateValue should be a callback that you create inside your functional component. That should take dependencies on the state that you define there. Use React.useCallback

Need some suggestions for a dynamic form using React

I'm building an enterprise-level application and I need some tips and suggestions for handling dynamic form.
The fields of the form are totally dynamic and they come differently for each user.
I loop through each field(fields come from an API call) on a file called renderUiType.js and based on a property of the field called uitype, we render different Inputs.
For example if uitype===1{render TextField}, if uitype===2{ render Checkbox } and so on...
So far the displaying part is correct but now I want to save the values of each field rendered and have them all in an object so I can do a POST API Call
So my question is, how can I do that? Should I create an onChange handler function for each form-element at the main file renderUiType.js and then pass it with props to the form-elements components or should I use Redux?
Any suggestion/article or anything is welcomed. Thank you
The folder structure looks like the image below(just in case it helps to understand what I ask)
..
You can use one callback function and use it in each onChange component specific handlers. You could have everything in state of the Form if you would like hidden under the unique keys/id, so you don't need to have Redux. f.e.
if (uitype===1)
{render <TextField value={this.state[fieldId]} onChange={this.onChange}/>}
if (uitype===2)
{ render <Checkbox value={this.state[fieldId]} onChange={this.onChange}/>}
or to simplify:
const getComponentByUIType = (uiType) => {
switch(uiType) {
case 1: return TextField
case 2: return Checkbox
}
}
// ...
onChange = fieldId => value => this.setState(state => ({fieldId: value}))
//...
render() {
getComponentByUIType(uiType).map(Component => <Component value={this.state[fieldId]} onChange = {this.onChange(fieldId)} />
}
Using Redux for this shouldn't be necessary unless you need to access this form's state somewhere outside the form. If you only need the form info to do a POST, I would keep all the data inside one component's state.
Just use the unique ID provided by the IP (the one you were gonna use for the POST) to build that state object. Every field will have an onChange that updates the main form component's state, and then that same value from the state is passed in to each field as a prop.

Changing class state from an imported function in ReactJS

I am trying to change the state of a class from an imported named component so I only need to write the code once. Is this even possible?
I have 3 files ( Login, ForgotPassword, Register ). On ALL of these files I am listening for an "onChange" event on the input fields that all do the same thing as show below:
onChange method:
onChange = (e) => {
this.setState(() => ({ errors: {} }));
let fields = this.state.fields;
fields[e.target.name] = e.target.value;
this.setState(() => {
return {
fields
}
});
};
I'd really like to import this as a named method along with some others that are working already:
import { onFocus, onBlur, onChange } from './Utils/Input';
The issue is (as seen above in the onChange code), that I need to update the class state from this method.
Is this at all possible? I am very new to React, so I might be going about this in the completely wrong way.
Thank you in advance!
When trying to update the state of a component you are always updating the state regarding to a particular this.
You are trying to write on* functions which are independent of the instances you are working with. So it makes no sense to use "this" inside those.
You could pass the instance of the Class to the on-function like this:
https://codesandbox.io/s/focused-cache-zzfvp
Use the method by binding the context to it from inside the class like this
onChange.bind(this)

How to Uncheck all checkboxes with a button. Input tag in child and button in parent. react - table

Im using react-table, See the following codesandbox (here)
So, I'm trying to bind an unCheck function to a button so all checkboxes I've selected will become unchecked. The button is in the parent component and ALL the checkboxes are in a child component called MyCheckbox.
I've tried so many things and It seems like refs will do. ( if you find another way I'm all ears)
Technically I've tried the following in another app here and it works, but in this case the function and the ref are inside the same component., so I'm guessing I have to pass refs? or maybe a callback. (sorry I'm kinda new at refs and Yes, I know they are bad practice)
this is the piece that is failing:
unCheck() {
let ref = "ref_";
this.refs[ref].checked = !this.refs[ref].checked;
}
how do I pass refs from child to parent? so my Uncheck function can use it.
PD.
Also, the ToggleAll () function selects and DESELECTS ALL checkboxes. this is a prop that react-table provides. however this is more of a on/off switch. I would like ONLY the OFF part of it. In my actual app im using redux too
Try this :)
unCheck = () => {
this.setState({ selection: [] });
};
Try this also...
unCheck = () => {
// let ref = "ref_";
// this.refs[ref].checked = !this.refs[ref].checked;
this.state.selectAll = true;
this.toggleAll();
};

How can I abstract multiple onChange events through a single React Function

I'm building a simple inventory system that uses bi-directional data flow to render a form from state, the form can then be updated by the user and changes feed back into state. So far so good. Now I'd like to simplify my code as I have a bunch of different onChange Handlers -as each form input has a unique handler. How can I simplify my code and have a single onChange handler? I tried passing the state attribute that I wish to edit through the callBacks - but this doesn't work. However if I explicitly specify the state attribute I wish to edit then it works fine.
The top example works but the bottom example doesn't. What am I missing here?
MethodUpdateInventoryState (key, event, updatedValue) {
var fishState = this.state.fishes;
var eventTarget = "name";
fishState[key].name = updatedValue;
this.setState({fishes: fishState});
}
MethodUpdateInventoryState (key, event, updatedValue) {
var fishState = this.state.fishes;
var eventTarget = "name";
fishState[key].eventTarget = updatedValue;
this.setState({fishes: fishState});
}
Gracias!

Categories

Resources