Focus issues with react - reactjs

Focus is not working on the input when "isFocussed" is true
componentWillReceiveProps(nextProps){
if(nextProps.isFocussed){
this.myRef.current.focus();
}
}
<input ref={this.myRef} />

You are not using createRef and trying to use focus method which is the issue.
Simply create callback ref and you are good to go.
Here is the working code below and codesandbox link.
index.js
import React from "react";
import ReactDOM from "react-dom";
import FocusComp from "./FocusComp";
class App extends React.Component {
state = {
focus: false
};
render() {
return (
<div className="App">
<button onClick={() => this.setState({ focus: true })}>
click me to focus
</button>
<br />
<br />
<FocusComp isFocussed={this.state.focus} />
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
FocusComp.js
import React from "react";
class FocusComp extends React.Component {
componentWillReceiveProps(nextProps) {
if (nextProps.isFocussed) {
this.myRef.focus();
}
}
render() {
return <input ref={myRef => (this.myRef = myRef)} />;
}
}
export default FocusComp;
I created a working code to make you understand what you did wrong.
Things to improve:-
1) use createRef instead of callback.
2) Don't use componentWillReceiveProps as it's deprecated.
Hope that helps!!!

Related

Can't get event.target.value in React

I'm trying to get a reaction from onInputChange function when I use it with onChange on input, but I didn't get why it's not console.log the value. Any help?
App.js
import React, { Component } from 'react';
import Output from './Components/Output';
import NumberInput from './Components/NumberInput';
import './App.css';
class App extends Component {
constructor() {
super()
this.state = {
decimal: 0,
inputString: ''
}
}
onInputChange = (event) => {
console.log(event.target.value)
}
render() {
const { decimal, inputString } = this.state;
return (
<fragment>
<h1>Binary to Decimal convertor</h1>
<NumberInput InputChange={this.onInputChange} />
<button>Submit</button>
<Output string={inputString}/>
</fragment>
);
}
}
export default App;
NumberInput component:
import React from 'react';
const NumberInput = ({ inputChange }) => {
return (
<fragment>
<input type='search' onChange={inputChange}></input>
</fragment>
)
}
export default NumberInput;
InputChange should be camelcase
change
<NumberInput InputChange={this.onInputChange} />
to
<NumberInput inputChange={this.onInputChange} />
you may also need to bind
<NumberInput inputChange={(e) => this.onInputChange(e)} />
Need some changes
Change your InputChange={this.onInputChange}
to inputChange={this.onInputChange} in App component.
because you are accessing inputChange in your NumberInput component.
And also change your fragment tag as well because you used fragment instead of Fragment tag.
Either use <Fragment>, <React.Fragment> or <> in NumberInput, App component like-
<Fragment>
<input type='search' onChange={inputChange}></input>
</Fragment>

In React how to PROPERLY pass input value from child to parent

I have a simple code in [sandbox][1] and below
[1]: https://stackblitz.com/edit/react-72dprn to pass input form value to child to parent but something is wrong and the value didn't get passed.
This is the app.js
import React, { Component } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
import './style.css';
import Form from './form'
class App extends Component {
constructor() {
super();
this.state = {
value: ""
};
}
handleSubmit = e=>{
this.setState({
value=e.target.value
})
}
render() {
return (
<div>
<Form onSubmit={this.handleSubmit}/>
</div>
);
}
}
render(<App />, document.getElementById('root'));
And the Form.js
import React, { Component } from 'react';
class form extends Component {
render() {
return (
<form className="replyForm" onSubmit={this.props.onSubmit}>
<input />
<button type="submit" className='btn btn-success'>Submit</button>
</form>); } }
export default form;
Any help greatly appreciated!
There are so many mistakes in your code. You should read the react docs properly
First of all you are setting your state incorrectly -
handleSubmit = e=>{
this.setState({
value: e.target.value //this is an object don't assign a value//
})
}
Second - In your form.js your component starts with a lowercase. React components start with an uppercase -
class Form extends Component {
render() {
return (
<form className="replyForm" onSubmit={this.props.onSubmit}>
<input />
<button type="submit" className='btn btn-success'>Submit</button>
</form>); } }
export default Form;
Now coming to your original question, To pass the value of input to child you need to pass it as props and use it in child as props -
<Form onSubmit={this.handleSubmit} inputValue={this.state.value} />
In your child component access that value as this.props.value.

React input element's onChange using setState() doesn't work

I want to make an app so that when text is typed in input element this will reflect that change in output. So far the updating doesn't work :(
import React, { Component } from 'react';
import './App.css';
import UserInput from './UserInput/UserInput';
import UserOutput from './UserOutput/UserOutput';
class App extends Component {
state = {
user: [
{ username: 'Kai' },
{ username: 'Orange' }
]
}
inputChangeHandler = (e) => {
this.setState(
{
user: [
{ username: e.target.value },
{ username: e.target.value }
]
}
)
}
render() {
return (
<div className="App">
<UserInput onChange={this.inputChangeHandler} />
<UserOutput username={this.state.user[0].username} />
<UserOutput username={this.state.user[1].username} />
</div>
);
}
}
export default App;
Change in text typed in input element should be reflected as username rendered in UserOutput. This doesn't work.
Here are codes for other components...
import React, { Component } from 'react';
class UserInput extends Component
{
render() {
return(
<div>
<input />
</div>
);
}
}
export default UserInput;
and
import React, { Component } from 'react';
class UserOutput extends Component
{
render() {
return(
<div>
<p>First paragraph and my name is {this.props.username}</p>
<p>Second paragraph </p>
</div>
);
}
}
export default UserOutput;
Ok there's your problem. You're not assigning the change handler to the input element in your UserInput component. It should be:
<input onChange={this.props.onChange} />

Send lower level component prop up to App

I am trying to send a prop up to the top level.
At the top level I'm trying to console.log the event text
At the moment I do not want to use Redux techniques
Here is the lower level component
import React, { Component } from "react";
export default class Search extends Component {
state = {
text: ""
};
onChange = e => {
this.setState({ [e.target.name]: e.target.value });
this.props.searchUsers(this.state.text);
};
render() {
return (
<div className="ui center aligned fluid container">
<div className="ui inverted segment">
<div className="ui inverted input">
<input
type="text"
name="text"
placeholder="Type Something"
value={this.state.text}
onChange={this.onChange}
/>
</div>
</div>
</div>
);
}
}
Then I try to console.log the text through an arrow function searchUsers
import React, { useEffect, useState } from "react";
import ReactDOM from "react-dom";
import Search from "./components/Search";
const App = () => {
searchUsers = text => {
console.log(text);
};
return (
<div className="App">
<Search searchUsers={this.searchUsers} />
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
export default App;
The Error I get
Please help me identify the problem.
In App component, you shouldn't use this and should use const
I think this should work
const App = () => {
const searchUsers = text => {
console.log(text);
};
return (
<div className="App">
<Search searchUsers={searchUsers} />
</div>
);
};
you can't use this inside stateless react component
Try this for index.js:
import React, { useEffect, useState } from "react";
import ReactDOM from "react-dom";
import Search from "./components/Search";
const App = () => {
const searchUsers = text => {
console.log(text);
};
return (
<div className="App">
<Search searchUsers={searchUsers} />
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
export default App;
Edit:
when I console.log I only see the letter after I type the next one...So if I physically type Hello...I console.log Hell.......any way to fix that ?
This is because you are passing the state as argument after setting the state. But setState is asynchronous so by that time the state is not set. You can either pass e.target.value or using callback in setState to invoke this.props.searchUsers
For eg:
onChange = e => {
this.setState({ [e.target.name]: e.target.value });
this.props.searchUsers(e.target.value);
};
This should fix your issue.
Hope it helps!

I am getting TypeError: this is undefined even after using this.handleChange = this.handleChange.bind(this) in constructor

I am getting an "TypeError: this is undefined" error even after I am binding this to the function in the constructor. I have also tried to use handleChange={this.handlChange.bind(this)} instead of this.handleChange = this.handleChange.bind(this) but it doesn't work. I am watching React tutorial and I wrote the same code as the tutor did, the code is working fine in his IDE but is showing error in mine.
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));
App.js
import React from 'react';
import './css/App.css';
import Header from "./components/Header"
import MainContent from "./components/MainContent"
import Footer from "./components/Footer"
class App extends React.Component {
render(){
return (
<div>
<Header />
<MainContent />
<Footer />
</div>
)
}
}
export default App;
MainContent.js
import React, {Component} from "react"
import ListItem from "./ListItem"
import tasks from "./tasks"
class MainContent extends Component
{
constructor()
{
super()
this.state =
{
tasks: tasks
}
this.handleChange = this.handleChange.bind(this);
}
handleChange(completed)
{
alert(completed)
}
render()
{
const taskComponents = this.state.tasks.map(function(data)
{
return <ListItem key={data.id} task={data.task} completed={data.completed} handleChange={this.handleChange} />
})
return (
<div>
{taskComponents}
</div>
)
}
}
ListItem.js
import React from "react"
let i=1;
class ListItem extends React.Component
{
render()
{
return (
<div>
<p style={{color : i%2 ? "black" : "orange"}}>
<input type="checkbox" checked={this.props.completed}
onChange={function(){
this.props.handleChange(this.props.completed)
}}>
</input> Task {i++} : <b>{this.props.task}</b>
</p>
</div>
)
}
}
export default ListItem

Resources