When the inputs are focused, I make the borders red with css.
But I can't autofocus on the most recently added input.
codesandbox: Example
import React from "react";
import "../src/styles.css";
class App extends React.Component {
constructor(props) {
super(props);
this.state = { values: [] };
}
createUI() {
return this.state.values.map((el, i) => (
<div key={i} style={{ marginBottom: "1rem" }}>
<style>
{`
.test:focus-within{
border:3px solid red !important;
}
`}
</style>
<div className="test">
<input type="text" />
</div>
</div>
));
}
addClick() {
this.setState((prevState) => ({ values: [...prevState.values, ""] }));
}
render() {
return (
<>
{this.createUI()}
<input
type="button"
value="add more"
onClick={this.addClick.bind(this)}
/>
</>
);
}
}
export default App;
How can I autofocus the last added input and make its borders red?
can create a useRef and assign it to the latest input
class App extends React.Component {
constructor(props) {
super(props);
this.state = { values: [] };
this.lastRef = React.createRef();
}
createUI() {
return this.state.values.map((el, i) => (
.....
<input ref={i === this.state.values.length - 1 ? this.lastRef : undefined} type="text" />
....
));
}
addClick() {
this.setState((prevState) => ({ values: [...prevState.values, ""] }),
() => {
this.lastRef.current.focus()
});
}
Demo
Related
Diet.js
export class Diet extends Component {
constructor(props) {
super(props);
this.state = {
list: [],
};
this.addToList = this.addToList.bind(this);
}
addToList(item) {
const list = [...this.state.list, item];
this.setState({ list });
}
render() {
<FoodCreate addToList={this.addToList} />
return (
<FoodList items={this.state.list} />
)}
FoodCreate
export class FoodCreate extends Component {
constructor(props) {
super(props);
this.state = {
FoodName: "",
calories: 0,
};
}
render() {
return (
<Button transparent>
<Icon
name="checkmark"
style={{ fontSize: 25, color: "red" }}
onPress={() => this.props.addToList(FoodName, calories)}
/>
</Button>
<TextInput
placeholder="Food Name"
placeholderTextColor="white"
style={styles.inptFood}
value={FoodName}
onChangeText={(FoodName) => this.setState({ FoodName: FoodName })}
/>
<TextInput
placeholder="Calories"
placeholderTextColor="white"
style={styles.inptMacros}
keyboardType="numeric"
value={calories}
maxLength={5}
onChangeText={(calories) => this.setState({ calories: calories })}
/>
FoodList
export class FoodList extends Component {
render() {
return (
<Content>
<List>
<ListItem itemDivider>
<Text>Food</Text>
{this.props.items.map((item, index) => {
return (
<ListItem key={index}>
<Text>{item.FoodName}</Text>
<Text>{item.calories}</Text>
</ListItem>
);
})}
</ListItem>
</List>
</Content>
);
}
}
export default FoodList;
Hi, I'm new to programming and React Native, so I'm trying to create a Grocery List by letting the user type FoodName and Calories and pressing the Icon: Check in FoodCreate page, and List it in the FoodList page, at the moment when I run the code gives me back an error: _this2.props.addToList is not a function, I've tried many solutions but I'm not sure where the error is.
class FoodCreate extends Component {
render() {
return (
<Button title="aaa" onPress={() => this.props.addToList('name')}></Button>
);
}
}
export default class Diet extends Component {
constructor(props) {
super(props);
this.state = {
list: [],
};
this.addToList = this.addToList.bind(this);
}
addToList(item) {
const list = [...this.state.list, item];
this.setState({list});
}
render() {
return <FoodCreate addToList={this.addToList} />;
}
}
I use the above code and didn't get the error
But I think you can have a better code
Don't use this.addToList = this.addToList.bind(this);, you can convert addToList to arrow function and remove this line
addToList = item => {
const list = [...this.state.list, item];
this.setState({list});
};
I am new in react Js and i want to build a multiple buttons like on link.
Can anybody help me .It will be very helpful to understand statements and components .
http://noxious-ornament.surge.sh/
i try to write something like this but i don't know how to continue.
import React, { Component } from 'react'
import './Ar.css';
class Ar extends Component {
constructor() {
super();
this.state = {
buttonPressed: 0
// 0 could be your default view
}
}
handleClick = (button) => {
this.setState({ buttonPressed: button })
}
render() {
return(
<div>
<button
className='button1'
onClick={() => this.handleClick(1)}
> BUTTON 1
</button>
<button
className='button2'
onClick={() => this.handleClick(1)}
> BUTTON 2
</button>
<button
className='button2'
onClick={() => this.handleClick(1)}
> BUTTON 3
</button>
}
</div>
)
}
}
export default Ar
This is a start. Next I'd add react-router-dom so you can load the SomePage component.
const {Component} = React;
function SomePage(props){
return (
<div>
Button {props.value} has been pressed!
<button>back</button>
</div>
)
};
class App extends Component {
constructor() {
super();
this.state = {
buttonPressed: 0,
buttonCount: [1,2,3,4,5]
}
}
handleClick = (event) => {
this.setState({ buttonPressed: event.target.id });
}
render() {
return(
<div>
{this.state.buttonCount.length > 0 ? this.state.buttonCount.map((item,index) => (
<button id={item} key = {index} onClick={()=>this.handleClick} className={`button${item}`}>
{item}
</button>
))
: null
}
</div>
)
}
}
// Render
ReactDOM.render(
<App />,
document.getElementById("react")
);
.button1 {
background-color: green;
}
.button2 {
background-color: blue;
}
.button3 {
background-color: red;
}
.button4 {
background-color: yellow;
}
.button5 {
background-color: purple;
}
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
You can have a state variable in the type of array:
this.state = {
buttonPressed: 0,
burronArray:[
{
id : 1,
name : "Button 1"
},
{
id : 2,
name : "Button 2"
},
]
}
and in the render function:
render() {
return(
<div>
{this.state.buttonArray.length > 0 ? buttonArray.map((button, index) => return(
<button
key={index}
value = {button.id}
className='button1'
onClick={() => this.handleClick(1)}
> {button.name}
</button>
)) : null}
</div>
)
}
I wrote this code for a todo list. It generates li elements but doesn't load the text stored in state.text.
class TodoWholistic extends React.Component {
constructor(props) {
super(props);
this.state = { tasks: [], text: "" };
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<input
id="new-task"
onChange={this.handleChange}
value={this.state.text}
placeholder="Type some text here..."
/>
<button>+</button>
</form>
<TodoList tasks={this.state.tasks} />
</div>
);
}
handleChange(e) {
this.setState({ text: e.target.value });
}
handleSubmit(e) {
e.preventDefault();
if (this.state.text.length === 0) {
return;
}
const newTask = {
tasks: this.state.text,
id: Date.now(),
};
this.setState((state) => ({
tasks: state.tasks.concat(newTask),
text: "",
}));
}
}
class TodoList extends React.Component {
render() {
return (
<ul>
{this.props.tasks.map((task) => (
<li key={task.id}>{task.text}</li>
))}
</ul>
);
}
}
ReactDOM.render(<TodoWholistic />, document.getElementById("root"));
<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>
<div id="root"></div>
Well, you are iterating over the state.tasks, which includes two property (tasks and id) and you are storing the state.text value in the tasks property which is kinda messy and I don't know your intention about it. But to solve your current problem you can either refer to the tasks property or change the tasks object key to text, where both of them are fine.
Refer to tasks:
class TodoWholistic extends React.Component {
constructor(props) {
super(props);
this.state = { tasks: [], text: "" };
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<input
id="new-task"
onChange={this.handleChange}
value={this.state.text}
placeholder="Type some text here..."
/>
<button>+</button>
</form>
<TodoList tasks={this.state.tasks} />
</div>
);
}
handleChange(e) {
this.setState({ text: e.target.value });
}
handleSubmit(e) {
e.preventDefault();
if (this.state.text.length === 0) {
return;
}
const newTask = {
tasks: this.state.text,
id: Date.now(),
};
this.setState((state) => ({
tasks: state.tasks.concat(newTask),
text: "",
}));
}
}
class TodoList extends React.Component {
render() {
return (
<ul>
{this.props.tasks.map((task) => (
<li key={task.id}>{task.tasks}</li>
))}
</ul>
);
}
}
ReactDOM.render(<TodoWholistic />, document.getElementById("root"));
<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>
<div id="root"></div>
Change tasks to text:
class TodoWholistic extends React.Component {
constructor(props) {
super(props);
this.state = { tasks: [], text: "" };
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<input
id="new-task"
onChange={this.handleChange}
value={this.state.text}
placeholder="Type some text here..."
/>
<button>+</button>
</form>
<TodoList tasks={this.state.tasks} />
</div>
);
}
handleChange(e) {
this.setState({ text: e.target.value });
}
handleSubmit(e) {
e.preventDefault();
if (this.state.text.length === 0) {
return;
}
const newTask = {
text: this.state.text,
id: Date.now(),
};
this.setState((state) => ({
tasks: state.tasks.concat(newTask),
text: "",
}));
}
}
class TodoList extends React.Component {
render() {
return (
<ul>
{this.props.tasks.map((task) => (
<li key={task.id}>{task.text}</li>
))}
</ul>
);
}
}
ReactDOM.render(<TodoWholistic />, document.getElementById("root"));
<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>
<div id="root"></div>
There is a typo in your TodoList class. task.text should be task.tasks
class TodoList extends React.Component {
render() {
return (
<ul>
{this.props.tasks.map((task) => (
<li key={task.id}>{task.tasks}</li>
))}
</ul>
);
}
}
When I type something in my textarea, and then click on the button, this new element is stocked inside an array and displayed in a list in my react app. I want the array's elements to be crossed when I click on them.
I've written a function to change the state of 'crossed' to its opposite when i click on the element, and then the style of the elements would change depending on whether it's true or false.
app.js:
import React from 'react';
import Tasks from './tasks.js';
import Item from './component.js';
import './App.css';
class App extends React.Component {
state = {
todolist: [],
crossed: false
}
addData(val) {
this.setState({ todolist: this.state.todolist.concat(val) },
() => console.log(this.state.todolist))
}
cross() {
this.setState({ crossed: !this.state.crossed },
() => console.log(this.state.crossed))
}
render() {
return (
<div className="App">
<Tasks onClick={value => this.addData(value)} />
{
(this.state.crossed) ? (<ul>
{this.state.todolist.map((e) => {
return <Item
item={e}
onClick={(e) => this.cross(e)}
style={{ textDecoration : 'line-through' }} />}
)
}
</ul>) : (
<ul>
{this.state.todolist.map((e) => {
return <Item
item={e}
onClick={(e) => this.cross(e)}
/>}
)
}
</ul>
)
}
</div>
);
}
}
export default App;
component.js:
import React from 'react'
class Item extends React.Component{
render(){ return(
<li onClick={this.props.onClick} style={this.props.style}>{this.props.item}
</li>
);
}}
export default Item
tasks.js :
import React from 'react'
class Tasks extends React.Component {
constructor(props) {
super(props)
this.state = {
value: '',
}
}
handleChange = e => {
this.setState({ value: e.target.value })
}
render() {
return (<div>
<textarea value={this.state.value} onChange={this.handleChange} ></textarea>
<button onClick={() => this.props.onClick(this.state.value)}>Add task</button>
</div>)
}
}
export default Tasks
I want each element to be crossed on its own when I click on it, but all the elements get crossed when I click on any one of them.
You should have some key for each object to differentiate,
addData(val) {
const tempObj = {
val: val,
crossed: false
}
this.setState({ todolist: this.state.todolist.concat(tempObj) },
() => console.log(this.state.todolist))
}
Now you will have crossed key for each object. I have not run the code, but this should work.
cross = e => {
e.crossed = !e.crossed;
}
(
<ul>
{this.state.todolist.map(e => {
return <Item
item={e}
onClick={(e) => this.cross(e)}
style={e.crossed && { textDecoration : 'line-through' }} />} // use ternary operator or this kind of && condition here
)
}
</ul>
)
I'm trying to get the value of child component yet not successful. Here what I am working on ...
import React from "react";
import Tooltip from "rc-tooltip";
import Slider, { Range } from "rc-slider";
const Handle = Slider.Handle;
const handle = props => {
const { value, dragging, index, ...restProps } = props;
return (
<Tooltip
prefixCls="rc-slider-tooltip"
overlay={value}
visible={dragging}
placement="top"
key={index}
>
<Handle value={value} {...restProps} />
</Tooltip>
);
};
const Slider = props => {
return (
<div>
<div style={{ width: 300, margin: 30 }}>
<p>{this.props.title}</p>
<Slider min={0} max={10} defaultValue={5} handle={handle}/>
</div>
</div>
);
};
export default Slider;
Main App.js
import Slider from '.....'
class App extends Component{
constructor(props){
super(props);
this.state = {
val: 0
}
}
render() {
return(
<Slider onChange={this.state.value} />
)
}
}
I am looking to get the value to be updated to this App.js state as the slider is being dragged. onChange is not updating the state. How should I modify so that slider value gets updated on this.state.value.
The Slider component from rc-slider has an onChange prop event which is a function. You need to pass this method to slider and update the state instead of just passing the state value
import React from "react";
import Tooltip from "rc-tooltip";
import Slider, { Range } from "rc-slider";
const Handle = Slider.Handle;
const handle = props => {
const { value, dragging, index, ...restProps } = props;
return (
<Tooltip
prefixCls="rc-slider-tooltip"
overlay={value}
visible={dragging}
placement="top"
key={index}
>
<Handle value={value} {...restProps} />
</Tooltip>
);
};
const Slider = props => {
return (
<div>
<div style={{ width: 300, margin: 30 }}>
<p>{this.props.title}</p>
<Slider min={0} max={10} defaultValue={5} onChange={props.onChange} handle={handle}/>
</div>
</div>
);
};
export default Slider;
class App extends Component{
constructor(props){
super(props);
this.state = {
val: 0
}
}
onChange=(value) => {
this.setState({val: value});
}
render() {
return(
<Slider onChange={this.onChange} />
)
}
}
Here is the Live code
https://codesandbox.io/s/n9y97y55kp
Let me know if you have any doubts
You just have to pass the event from child to parent component to update the values.
according to rc-slider document, you should pass a function to Slider onChange.
import Slider from '.....'
class App extends Component {
constructor(props) {
super(props);
this.state = {
val: 0
}
}
handleSliderChange = (value) => {
console.log(value) // maybe a string or a object
this.setState({val: value})
}
render() {
return (
<Slider onChange={this.handleSliderChange} />
)
}
}
above code should work