Calling a ref from another component (?) - javascript

I am working with React in a chat application. I need that evertytime you click on the chat box the input where you enter your messagges, should be focused.
The problem I have is that the chat box which is in the main component, is separately from the component where the input to enter the messages is.
Look, main component
class ChatView extends React.Component {
constructor (props) {
super(props);
this._inputFocus = this._inputFocus.bind(this);
}
_inputFocus () {
let input = React.findDOMNode(this.refs.SHOULDFOCUS-HERE);
input.focus();
}
render () {
if (this.props.mode === 'player') {
dealerPlayerMessages = <ul ref="messages">{messages}</ul>;
// CHAT FORM IS THE COMPONENT CONTAINING THE INPUT
chatForm = <ChatForm onAddMessage={this.addMessage} />;
chatBox = <div>{dealerPlayerMessages}{chatForm}</div>
}
return <div className="dealer-player-box" onClick={this._inputFocus} >
{chatBox}
</div>;
}
}
so, as you see, when you click in the div with class name dealer-player-box, the function this._inputFocus is called.
But the input to enter your message text, is in the component ChatForm:
class ChatForm extends React.Component {
constructor (props) {
super(props);
}
render () {
return (<div className="chat-form">
// THIS IS THE INPUT I NEED TO FOCUS ON
<input className="input-form"
placeholder="Your message..."
ref="SHOULDFOCUS-HERE"
autofocus="true" />
</div>);
}
}
so, from the main component, what should I do in order to focus on that input since in another component ?

Add a ref to your ChatForm:
<ChatForm ref="chatForm" onAddMessage={this.addMessage} />;
In your ChatForm change the input ref to something meaningful:
<input className="input-form"
placeholder="Your message..."
ref="chatInput"
autofocus="true" />
In your ChatForm component add a method which focuses:
focusInput() {
this.refs.chatInput.focus();
}
In your ChatView component modify the _inputFocus method:
_inputFocus() {
this.refs.chatForm.focusInput();
}
Note that using refs might be a little different if you are using deprecated versions of react (<0.14).

Related

React JS validate form

Hello friends I'm pretty new to React JS so I want to ask you this:
I have a Parent and Child component. In Child component I have inputs (name,email etc) and in Parent component I have Button to save the input data in database.
My question is: How to validate inputs(i want them to be required) so the button can NOT call saveData function(to save in database) if the inputs are empty.
Here is Parent Component:
class Parent extends Component{
saveData = (e) => {
//some code
}
render() {
return (
<div>
<Child/>
<Button color="primary" onClick={this.saveData}>Submit</Button>
</div>
);
}
}
And here is Child Component:
class Child extends React.Component {
onInputChange = (e) => {
e.preventDefault();
this.props.onInputChange(e.target.name, e.target.value);
};
render() {
return (
<FormGroup>
<Input name="email" onChange={this.onInputChange}/>
</FormGroup>
);
}
}
I cant see the implementation of your onInputChange function but looks like its coming from parent component.
So, if you have onInputChange in your parent component then, you can have a disable state that is passed to your Button component and you need to set that disable state when onInputChange is called i.e
onInputChange = (name, value) => {
if(value === ''){
this.setState({disable: true});
}
else{
this.setState({
name: value;
disable:false
})
}
}
And pass it to your button i.e.
<Child />
<Button color="primary" disabled={disable} onClick={this.saveData}>

React onChange doesn't fire on text input when formatter.js is used

I'm using a formatter.js to format some input box. I want to connect this formatter to my react app so I've write a simple module but onChange function doesn't fire. When I remove the formatter library the input box works as planned. But I want to format the inputs and also use the values inside my React application.
After a brief search over the internet I've came across with this question;React: trigger onChange if input value is changing by state? but I'm not sure how can I apply that solution to my application.
ReactMaskedInput.js
import React, { Component } from 'react'
class ReactMaskedInput extends Component {
constructor(props) {
super(props)
this.onChangeHandler = this.onChangeHandler.bind(this)
this.state = {
value: ""
}
}
onChangeHandler(event) {
this.setState({
value: event.target.value
})
alert(this.state.value)
}
componentDidMount() {
let dataMask = this.props.dataMask
window.$(`#${this.props.id}`).formatter({
pattern: dataMask
});
}
render() {
return (
<div >
<h3>
<b>{this.props.header}</b>
</h3>
<input
id={this.props.id}
type="text"
placeholder={this.props.placeHolder}
className="form-control"
onChange={event => this.onChangeHandler(event)}
name={this.props.name}
>
</input>
</div>
)
}
}
export default ReactMaskedInput
Index.js
ReactDOM.render(<ReactMaskedInput
id="myMaskedInput"
header="Masked Input Phone"
onChange={(event) => { deneme(event); }}
dataMask={"({{999}}) {{999}}-{{9999}}"}
name="maskedInput1"
placeHolder="Please enter a valid phone number"
validationInitiatorNr={10}
// onChange={(phoneNr) => validatePhone(phoneNr)}
/>, document.getElementById('myFormattedInput'))
Fix your onChangeHandler code
You have to call the 'onChange' handler you passed as an attribute in code of your ReactMaskedInput class explicitly. I guess you are assuming that it would get called automatically. Note that ReactMaskedInput is a component you created, and not an HTML tag 'onChange' of which gets called by React.
onChangeHandler(event) {
this.setState(() => ({
value: event.target.value
}), () => {
this.props.onChange(event) // Call 'onChange' here
alert(this.state.value) // alert should be inside setState callback
})
}

Managing large forms - ReactJS

I was reading about react forms, and I just can read about two ways of managing data in forms.
The first one - refs, putting refs in each data input:
class CustomTextInput extends React.Component {
constructor(props) {
super(props);
this.focus = this.focus.bind(this);
}
focus() {
// Explicitly focus the text input using the raw DOM API
this.textInput.focus();
}
render() {
// Use the `ref` callback to store a reference to the text input DOM
// element in this.textInput.
return (
<div>
<input
type="text"
ref={(input) => { this.textInput = input; }} />
<input
type="button"
value="Focus the text input"
onClick={this.focus}
/>
</div>
);
}
}
and the second one Controlled Forms, putting a handler for each data input:
import React, { Component } from 'react';
import Form from 'react-form-controlled';
export default class Example extends Component {
constructor(props, context) {
super(props, context);
this.state = {
users: [{
firstName: 'Zlatko'
}, {
firstName: 'Livia'
}]
};
}
onChange = (data) => {
this.setState(data);
}
onSubmit = (data) => {
alert(`Hi ${data.users[0].firstName}`);
}
render() {
return (
<Form
value={this.state}
onChange={this.onChange}
onSubmit={this.onSubmit}
>
<fieldset name="users">
<label>
<input name="firstName" />
</label>
</fieldset>
<button type="submit">Submit</button>
</Form>
);
}
}
So, imagine you have a large form with a lot of data input, will you have to declare all the handler functions for each input in the form? (also, the total of bindings in the constructor)
Wouldn't it be convenient to just submit a just read form.input1, form.input2? I mean, somehing like this:
onSubmit(formValues){
payload = [
{'value1': formValues.input1 },
{'value2': formValues.input2 },
...
{'valueN': formValues.inputN },
]
}
without going to reading it from state?
I any case, is it and advantage to have a smart component with a lot of handlers for managing form values? or maybe the other approach, having a refs for each component in the form?
I would suggest to check redux + redux-form combo. Managing form state with these modules is piece of case. You can have functional components without any local state or handlers.

React - Can A Child Component Send Value Back To Parent Form

The InputField & Button are custom components that go into a form to create a form. My issue is how do I send the data back up to form so that on button click, I can fire ajax on the form with data (username & password):
export default auth.authApi(
class SignUpViaEmail extends Component{
constructor(props){
super(props);
this.state = {
email : "",
password : ""
};
this.storeEmail = this.storeEmail.bind( this );
this.storePassword = this.storePassword.bind( this );
}
storeEmail(e){
this.setState({ email : e.target.value });
}
storePassword(e){
this.setState({ password : e.target.value });
}
handleSignUp(){
this.props.handleSignUp(this.state);
}
render(){
return(
<div className="pageContainer">
<form action="" method="post">
<InputField labelClass = "label"
labelText = "Username"
inputId = "signUp_username"
inputType = "email"
inputPlaceholder = "registered email"
inputClass = "input" />
<Button btnClass = "btnClass"
btnLabel = "Submit"
onClickEvent = { handleSignUp } />
</form>
</div>
);
}
}
);
Or Is it not recommended & I should not create custom child components within the form?
child component => InputField
import React,
{ Component } from "react";
export class InputField extends Component{
constructor( props ){
super( props );
this.state = {
value : ""
};
this.onUserInput = this.onUserInput.bind( this );
}
onUserInput( e ){
this.setState({ value : e.target.value });
this.props.storeInParentState({[ this.props.inputType ] : e.target.value });
}
render(){
return <div className = "">
<label htmlFor = {this.props.inputId}
className = {this.props.labelClass}>
{this.props.labelText}
</label>
<input id = {this.props.inputId}
type = {this.props.inputType}
onChange = {this.onUserInput} />
<span className = {this.props.validationClass}>
{ this.props.validationNotice }
</span>
</div>;
}
}
Error : I get the error e.target is undefined on the parent storeEmail func.
React's one-way data-binding model means that child components cannot send back values to parent components unless explicitly allowed to do so. The React way of doing this is to pass down a callback to the child component (see Facebook's "Forms" guide).
class Parent extends Component {
constructor() {
this.state = {
value: ''
};
}
//...
handleChangeValue = event => this.setState({value: event.target.value});
//...
render() {
return (
<Child
value={this.state.value}
onChangeValue={this.handleChangeValue}
/>
);
}
}
class Child extends Component {
//...
render() {
return (
<input
type="text"
value={this.props.value}
onChange={this.props.onChangeValue}
/>
);
}
}
Take note that the parent component handles the state, while the child component only handles displaying. Facebook's "Lifting State Up" guide is a good resource for learning how to do this.
This way, all data lives within the parent component (in state), and child components are only given a way to update that data (callbacks passed down as props). Now your problem is resolved: your parent component has access to all the data it needs (since the data is stored in state), but your child components are in charge of binding the data to their own individual elements, such as <input> tags.
Addendum
In response to this comment:
What if we render a list of the child component? Using this single source of truth in Lifting state up technique will let the parent controls all the state of all the child inputs right? So how can we access each of the value input in the child component to (which is rendered as list) from the parent component?
For this case, you may map a child component for each element in the list. For example:
class Parent extends Component {
//...
handleChangeListValue = index => event => {
this.setState({
list: this.state.list
.map((element, i) => i === index ? event.target.value : element)
});
}
//...
render() {
return this.state.list.map((element, i) => (
<Child
value={element}
onChangeValue={this.handleChangeListValue(i)}
/>
));
P.S. Disclaimer: above code examples are only for illustrative purposes of the concept in question (Lifting State Up), and reflect the state of React code at the time of answering. Other questions about the code such as immutable vs mutable array updates, static vs dynamically generated functions, stateful vs pure components, and class-based vs hooks-based stateful components are better off asked as a separate question altogether.
React class component
Parent.js
import React, { Component } from 'react';
import Child from './child'
class Parent extends Component {
state = {
value: ''
}
onChangeValueHandler = (val) => {
this.setState({ value: val.target.value })
}
render() {
const { value } = this.state;
return (
<div>
<p> the value is : {value} </p>
<Child value={value} onChangeValue={this.onChangeValueHandler} />
</div>
);
}
}
export default Parent;
Child.js
import React, { Component } from 'react';
class Child extends Component {
render() {
const { value , onChangeValue } = this.props;
return (
<div>
<input type="text" value={value} onChange={onChangeValue}/>
</div>
);
}
}
export default Child;
React hooks
Parent.js
import { useState } from "react";
import Child from "./child";
export default function Parent() {
const [value, changeValue] = useState("");
return (
<div>
<h1>{value}</h1>
<Child inputValue={value} onInputValueChange={changeValue} />
</div>
);
}
Child.js
export default function Child(props) {
return (
<div>
<input
type="text"
value={props.inputValue}
onChange={(e) => props.onInputValueChange(e.target.value)}/>
</div>
);
}
Parent.js
import SearchBar from "./components/SearchBar";
function App() {
const handleSubmit = (term) => {
//Log user input
console.log(term);
};
return (
<div>
<SearchBar onPressingEnter={handleSubmit} />
</div>
);
}
export default App;
Child.js
import { useState } from "react";
function SearchBar({ onPressingEnter }) {
const [UserSearch, setname] = useState("[]");
/* The handleChange() function to set a new state for input */
const handleChange = (e) => {
setname(e.target.value);
};
const onHandleSubmit = (event) => {
//prevent form from making a http request
event.preventDefault();
onPressingEnter(UserSearch);
};
return (
<div>
<form onSubmit={onHandleSubmit}>
<input
type="search"
id="mySearch"
value={UserSearch}
onChange={handleChange}
name="q"
placeholder="Search the siteā€¦"
required
/>
</form>
</div>
);
}
export default SearchBar;
You can add a "ref name" in your InputField so you can call some function from it, like:
<InputField
ref="userInput"
labelClass = "label"
labelText = "Username"
inputId = "signUp_username"
inputType = "email"
inputPlaceholder = "registered email"
inputClass = "input" />
So you can access it using refs:
this.refs.userInput.getUsernamePassword();
Where getUsernamePassword function would be inside the InputField component, and with the return you can set the state and call your props.handleSignUp

onclick show and hide data in react.js

i have component which is showing data in the webpage
I want to write another component and create buutton in it. which just hide other component on clicking the button and show basic input field form.
My code is something like this
component app
class App extends React.Component{
constructor(props) {
super(props);
this.state= {
filter: null,
};
this.setFilter = this.setFilter.bind(this);
}
setFilter(filter) {
this.setState({filter: filter})
}
render(){
let filteredPassword = details_data.filter(
(detail) =>{
console.log(detail.website.toLowerCase(), this.state.filter)
return detail.website.toLowerCase().indexOf(this.state.filter)!= -1;
}
);
return (
<ul>
<Filter onUpdateFilter={this.setFilter} />
{
filteredPassword.map((detail)=>{
return <Detail item={detail}
key={detail.id}/>
})
}
</ul>
)
}
}
Another Detail component
class Filter extends React.Component{
constructor() {
super();
this.state={
search: 'Search'
}
}
updateSearch(event) {
this.props.onUpdateFilter(event.target.value.substr(0,40))
}
formShow(){
}
render() {
return (
<div>
<input id="search" type="text" placeholder={this.state.search} onChange={this.updateSearch.bind(this)}/>
<input id="button1" type="button" value="+" onClick={this.formShow()}/>
</div>
)
}
}
Few other component like this.
i am trying to hide the table and form button above is used to "show form" button.
class Form extends React.Component {
render() {
return(
<div>
<form>
<input type="text" placeholder="username" />
<input type="password" placeholder="username" />
</form>
</div>
)
}
}
Guide me how to do this.. thank you
Without looking too much to your code (it's a bit messy) it seems to me what you want to achieve is to communicate two components. Component A will react to a button click event and tell: 1) component B to hide and 2) component C to show up.
The way of doing this depends on if the components have hierarchical relationship or not. I would recommend start by reading this chapter of the official React documentation. Then, here is also a great article on component communication strategies in React.
On top of that, some patterns that focus specifically on this have achieved great success, like Flux or Redux.
Hope it helps.

Categories

Resources