Hello thanks for the help in advance. I explain the behavior I want to achieve in react. Here is the sandbox for a better understanding. The behavior of the code is as follows:
There is a div marked with a 1px border and inside it there is a button and another div where it will render an array. Clicking on the button adds that same button to the array and renders it alongside the first one. Multiple clicks on the first button will generate a column of buttons next to the first button. So far so good.
What I want to achieve is that clicking on any of the buttons in the column generates another column of buttons next to the button we click on. And so on. At this point, I'm stuck. Thank you.
import "./styles.css";
import { useState } from "react";
export default function App() {
const [btnCount, setBtnCount] = useState([]);
const style = {
maxWidth: "100px",
display: "flex",
padding: "10px",
border: "solid 1px"
};
function handleAdd() {
setBtnCount(btnCount.concat(btn));
}
const btn = <button onClick={handleAdd}>Click</button>;
return (
<div>
<div style={style}>
<div style={{ margin: "5px" }}>{btn}</div>
<div>
{btnCount.map((e, index) => {
return <div key={index}>{e}</div>;
})}
</div>
</div>
</div>
);
}
Related
Consider the following structure:
.container {
width: 200px;
height: 100px;
overflow: auto;
overflow-y: hidden;
}
.container p {
width: 300px;
height: 100px;
background-color: yellow;
}
<div class="container">
<p>Sample Text1, Sample Text2, Sample Text3</p>
</div>
<button onclick="handleScrollLeft()">Left</button>
<button onclick="handleScrollRight()">Right</button>
Because I'm working in ReactJS, my real code looks more like this:
export function Slider() {
const handleScrollLeft = () => {
}
const handleScrollRight = () => {
}
return (
<>
<div className="container">
<p>Sample Text1, Sample Text2, Sample Text3</p>
</div>
<button onClick="handleScrollLeft">Left</button>
<button onClick="handleScrollRight">Right</button>
</>
);
}
With those 2 buttons I would like to change the scroll value (move left and right respectively). I'm not sure how to handle this kind of change:
In useEffect? (I don't want to force re-render, just expand the scroll functionality to those 2 buttons)
Create custom hook? (Same concern)
Or should I directly modify that DOM element in the handler functions? (I know this is a big no-no in React)
I'm really confused on which approach is correct, any advise or solution with further explanation on why would be appreciated
You can use the useRef hook and the element.scrollBy method.
const STEP = 40;
export function Slider() {
const scrollable = useRef(null);
const handleScrollLeft = () => {
scrollable.current.scrollBy(-STEP, 0);
}
const handleScrollRight = () => {
scrollable.current.scrollBy(STEP, 0);
}
return (
<>
<div className="container" ref={scrollable}>
<p>Sample Text1, Sample Text2, Sample Text3</p>
</div>
<button onClick="handleScrollLeft">Left</button>
<button onClick="handleScrollRight">Right</button>
</>
);
}
You can also use this sandbox as an example.
I am struggling with my React Native App!!!!
I have a simple Flatlist.
I have a TextInput that has a filter option.
Click inside the TextInput. A dropdown of filter appears.
Click on that Filter it appears inside the TextInput.
Need some help in styling this!!! It should look somewhat like this. If not to this extent at least a box around it is fine.
I tried it with a Button - React Native elements. It's so so so frustrating. I cannot use any 3rd party libraries (company policy).
TextInput Code:
<Icon type='materialicons' name='search' /> // search icon
<Button icon={<Icon name="check"/>}. //my attempt to create a button around the filter
type='clear' title ={val}
onPress={()=>{this.handleFilterIcon(false); this.setFilt(false)}}/>
<TextInput // Text Input
value={value}
placeholder='Search Here...'
onChangeText={(text)=>{this.handleSearch(text, true);this.renderDropDown(false)}}
onTouchStart={()=>{this.setTempNotifications();this.renderDropDown(true)}}
style={{ height: 40, flex: 1}}
autoCapitalize='none'
selectTextOnFocus={true}
label='input'
/>
<Icon type='materialicons' name='cancel' onPress={()=>{} /> // Clear Icon
<Button title='Cancel'
buttonStyle={{backgroundColor:'#D3D3D3', borderColor: 'grey', borderRadius: 6 , borderWidth: 1, height: 40}}
onPress={()=>{} /> // Cancel button
Anyone please tell me the most efficient way to do this!!!
The only way I'm seeing is, since you don't have to use third party libraries is this:
Create a an empty label next to the input. Wrap these two with a div with position:relative
As soon as input is entered, put the same text in this label. Customise this label with styling: position:absolute;background:grey...
Just to give you some idea, here's an implementation in JQuery. You have to take this forward and ask specific question where you're struggling.
function inputChange(val){
$('label').text(val);
$('input').val("");
}
label{
border:1px solid;
border-radius: 5px;
position: absolute;
background: grey;
left:2px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<input type="text" onchange="inputChange(this.value)"/>
<label></label>
</div>
In React the same implementation could look something like this. You can create a file with this implementation, import in your App.js and see. Take this idea fowrward and change the styling and behaviours as per the need.
import React, { Component } from 'react';
class CustomInputTextstyling extends Component {
constructor(props) {
super(props);
this.state ={
inputText: ""
}
}
handleInputChange(e){
this.setState({inputText: e.target.value});
}
render() {
const wrapperDiv = {
position: 'relative'
}
const label = {
border:'1px solid',
borderRadius: '5px',
position: 'absolute',
background: 'grey',
left:'2px'
}
return (
<div style={wrapperDiv}>
<input type = "text" onBlur = {this.handleInputChange.bind(this)}></input>
<label style={label}>{this.state.inputText}</label>
</div>
);
}
}
export default CustomInputTextstyling;
I am using semantic UI React . I included semantic UI React Button but default it showing in Left , I want to show it in Right . Someone please help me how I can move semantic button to right .
<Button.Group>
<Button>Cancel</Button>
<Button.Or />
<Button positive>Save</Button>
The beautiful one solution is just to add floated="right" to your Button.Group like that:
<Button.Group floated="right">
<Button>Cancel</Button>
<Button.Or />
<Button positive>Save</Button>
</Button.Group>
You can also check this: https://codesandbox.io/s/n0wzzxxl0m
All the options for Button.Group are provided here: https://react.semantic-ui.com/elements/button/
You can achieve that via wrapping the button group in a container that will align its children to the right via css.
css:
.rightAlign {
display: flex;
justify-content: right;
}
Button component in wrapping container:
import React from "react";
import { Button } from "semantic-ui-react";
const MyButtons = () => {
return (
<div className="rightAlign">
<Button.Group>
<Button>Cancel</Button>
<Button.Or />
<Button positive>Save</Button>
</Button.Group>
</div>
);
};
export default MyButtons;
See it working here: https://codesandbox.io/s/3yqy09k35m?fontsize=14
I'm learning React.Js. I'm trying to attach an event to write something in the console, however i cant get my function to trigger. Does anyone know how i would attach an onClick event to a react div? I apologise if this is a basic question but ive tried several different methods and none of them are working.
I have tried the two ways of triggering the function shown below but neither is working.
So, Ive realised that the reason that the events were not working was because I was rendering server side. If i render on the client then the event triggers. Does anyone know how to make it trigger if i have initially rendered on the server?
class Individual extends React.Component {
handleClick = () => {
alert("GREAT");
}
render() {
const indDiv = {
margin: '5px',
width: '100px',
height: '120px',
cursor: 'pointer',
border: '5px solid pink',
color: 'blue',
float: 'left'
};
return (
<div>
<div onClick={this.handleClick.bind(this)}>
Alert 1
</div>
<div onClick={() => this.handleClick}>
Alert 2
</div>
<div style={indDiv}>
{this.props.num}. {this.props.name}.
</div>
</div>
);
}
}
Thank you to everyone that contributed to this. After everything i found that because i had initially created this as a server rendered piece, I had to attach the events after the page had rendered. I was using ReactJS.Net and had to initialize it seperately using hydrate.
Both the ways of calling handler function is incorrect in your code.
In your code handleClick is an arrow function hence manual binding is not required.
If it is not an arrow function then the manual binding should be done always in constructor only. Never do binding anywhere else like you did in render.
When you use onClick={() => this.handleClick} this is wrong. It should be onClick={()=> this.handleClick()}. If no Paranthesis then this is correct onClick={this.handleClick}
So change
<div onClick={this.handleClick.bind(this)}>
Alert 1
</div>
<div onClick={() => this.handleClick}>
Alert 2
</div>
To
<div onClick={()=> this.handleClick()}>
Alert 1
</div>
<div onClick={() => this.handleClick()}>
Alert 2
</div>
The reason you should not do binding anywhere else in the component except constructor because for eg you did binding directly in render so what happens in this case is it creates a new function in webpack bundle file every time the component renders and re renders again hence bundle file grows large. Hence it is recommended to bind it only in constructor
You need to declare the handler method after the render method. Here is a basic implementing of your code in jsfiddle.
https://jsfiddle.net/ufyxwv8p/
class Individual extends React.Component {
render() {
const indDiv = {
margin: '5px',
width: '100px',
height: '120px',
cursor: 'pointer',
border: '5px solid pink',
color: 'blue',
float: 'left'
};
return (
<div>
<div onClick={this.handleClick}>
Click to show in console
</div>
<div style={indDiv}>
{this.props.num}. {this.props.name}.
</div>
</div>
);
}
handleClick = () => {
console.log('this is:', this);
}
}
ReactDOM.render(<Individual/>,document.getElementById("app"))
here try like this the way you are defining your handleclick function is wrong i have edited your code online on sandbox to make it work. call function the way you are calling on Alert 1 than define function the way I have uploaded an image
Link of codesandbox of your code check that
Check this image of that code if you dont have time to go through whole code
The click handler on Alert 1 is already working. It's not necessary to bind when you use a the () => {} class properties syntax.
Your click handler on Alert 2 isn't working because you've written an inline arrow function which returns another function. You need to call it, like () => this.handleClick().
Here is a working snippet of your code.
class Individual extends React.Component {
handleClick = () => {
alert("GREAT");
};
render() {
const indDiv = {
margin: "5px",
width: "100px",
height: "120px",
cursor: "pointer",
border: "5px solid pink",
color: "blue",
float: "left"
};
return (
<div>
<div onClick={this.handleClick}>Alert 1</div>
<div onClick={() => this.handleClick()}>Alert 2</div>
<div style={indDiv}>
{this.props.num}. {this.props.name}.
</div>
</div>
);
}
}
ReactDOM.render(<Individual />, document.getElementById("app"));
<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="app"></div>
You have to use bind
onClick={this.handleClick.bind(this)}
or use arrow function
onClick={()=>this.handleClick()}
class Individual extends React.Component {
handleClick = () => {
alert("GREAT");
};
render() {
const indDiv = {
margin: "5px",
width: "100px",
height: "120px",
cursor: "pointer",
border: "5px solid pink",
color: "blue",
float: "left"
};
return (
<div>
<div onClick={this.handleClick}>Alert 1</div>
<div onClick={this.handleClick}>Alert 2</div>
<div style={indDiv}>
{this.props.num}. {this.props.name}.
</div>
</div>
);
}
}
ReactDOM.render(<Individual />, document.getElementById("app"));
I'm relatively new with ReactJS and I'm trying to implement a small form that contains an input text field and a search button. I'm using the :focus pseudo-selector on the input field so when the user enters information it increases the width to 2000% and when the element loses focus it goes back to width:130%.
The problem I'm having is when I click my search button for the first time the input field shrinks back to the original position but it doesn't do the search until I click it for the second time. If I type something and then click somewhere else to loose focus it works like a charm.
Here's my code:
import React from 'react'
import Header from '../base/header'
import axios from 'axios'
import SearchResults from './searchResults'
import ReactCSSTransitionGroup from 'react-addons-css-transition-group';
import Radium from 'radium';
class Search extends React.Component {
constructor(props) {
super(props)
this.state = {
searchTerm: "",
searchResultsList: ""
}
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleCallback = this.handleCallback.bind(this);
}
handleCallback() {
console.log("calling handleSubmit");
}
handleSubmit() {
var that = this
event.preventDefault();
axios.post('http://localhost:3000/users/findusers', {
searchTerm: this.state.searchTerm
}).then(function (response) {
console.log("data sent");
that.setState({searchResultsList: response.data})
}).catch(function (error) {
console.log(error);
});
}
handleChange(e) {
this.setState({searchTerm: e.target.value}, () => {
console.log(this.state.searchTerm);
});
}
render() {
return (
<div>
<Header/>
<form onSubmit={this.handleSubmit}>
<div>
<ReactCSSTransitionGroup
transitionName="search-input"
transitionAppear={true}
transitionAppearTimeout={500}
transitionEnter={false}
transitionLeave={false}>
<input
type="text"
style={styles.inputStyle}
value={this.state.searchTerm}
onChange={this.handleChange}
placeholder="Find Friends..."
/>
{/*<img onClick={() => this.handleSubmit()} */}
<img src="/icons/svg/magnifying-glass.svg"
alt="Search" className="searchIcon"
onClick={() => this.handleCallback()}
/>
</ReactCSSTransitionGroup>
</div>
</form>
<div className="container-fluid">
<div className="row">
<div className="col-md-3">left</div>
{/* Main Area */}
<div className="col-md-6">
<SearchResults
searchResultsList={this.state.searchResultsList}
/>
</div>
<div className="col-md-3">right</div>
</div>
</div>
</div>
)
}
}
const styles = {
inputStyle: {
marginTop: 5,
marginLeft: 20,
width: 130,
WebkitTransition: 'width 0.4s easeInOut',
msTransition: 'width 0.4s easeInOut',
':focus': {
width: '2000%'
}
}
};
export default Radium(Search)
I originally had the code in a separate CSS file and decided to make it inline to see if there was any difference. I tried creating different functions to see if there was any difference but is still behaving the same.
I would really appreciate any help!
In regards to the width changing when clicking the magnifying glass. I believe it is because the :focus property is on the input and not the div containing the input and img.
I would recommend using the :focus-within property on the parent div. Here is an example of divs with both properties.
#div1:focus-within > input {
width: 300px;
}
#div2 > input:focus {
width: 300px;
}
<div id="div1">
<input type="text"/>
<button>Search</button>
</div>
<div id="div2">
<input type="text"/>
<button>Search</button>
</div>
This should solve the focusing issue.
Not sure why your magnifying glass image works so strangely. When reading the code it seems that clicking the image calls handleCallback() which is only logging not submitting.
Not sure if this helps but I would recommend using a button or input element for submission. The button would have type="submit" with the magnifying glass image as the child. The input would have type="submit" value="" and set the CSS background-image: to the magnifying glass.