React element events - reactjs

So I'm trying to style an element when user focuses/hovers on an input/button. The way I'm doing it is by using a state and setting it to true or false if the user has hovered or focused but find it very repetitive and will take a lot of code, considering I would have to create a focused and hovered state for each button or input.
For example, I'm doing :
const [hoveredBtn, setHoveredBtn] = useState(false)
const [themecolor, setThemecolor]=useState('red') //this state is being from firebase, red would
//just be an example, it can be whatever the user sets it to.
return (
<button
onMouseOver={()=>setHoveredBtn(true)}
onMouseLeave={()=>setHoveredBtn(false)}
style={hoveredBtn?{backgroundColor: themecolor}:{backgroundColor:"white"}}
>
Button
</button>
)
Therefore, I would need to create a hovered variable for each button or input I have and im looking to know if there is a way to do it like this, but when I tried I get an error:
return (
<button onMouseOver={this.style.color=themecolor} onMouseLeave=
{this.style.color='white'}>Button</button>
)

You can’t specify pseudo-classes using inline styles. That means :hover, :focus, :active, or :visited go out the window rather than the component.
source: https://www.freecodecamp.org/news/react-styled-components-inline-styles-3-other-css-styling-approaches-with-examples/
style.css:
.myComponent:hover {
// define style
}
myReactComponent.jsx:
import './style.css';

Related

How to call or use a .js file using onclick Reactjs functional component

I have .js file called Edit which is used for edit purpose. I have another .js file called Add. I have a dialog box in edit.js which will open when I click a button. But I don't want to use a button instead I want to get that a dialog box when I click anywhere on box. I tried using onclick in div tag but I didn't get any response.
this is the output
so if you observe we got a edit button there if click it I am getting form/dialog box for editing the content. but I want that form or dialog box to open when I click anywhere on the yellow box.
<div id='color' className='div2' key={item.id} style={{width: 340,
# border: '5px solid white',textIndent:-30,paddingRight:32,paddingLeft:40,whiteSpace:'pre',paddingTop:15, backgroundColor:item.currentColor}} onClick={()=>{editpage(item.id)}} >
this is what I used for calling function for getting form in another .js file. It is part of a mapping function.` there is a onclick event I used that whenever I click on the box or content which is all under div tag I need to go to that function and there go to edit and then form but it didn't work
the function to which it goes is this:
const editpage=(id)=>{ <Edit id={id}></Edit> }
I want to send a id as a parameter which is passed to Edit.js.
I used <Edit/> because it is a another js file which I am importing in Add.js file.
I am not able to get the output can you please me with this.
how I can use this when I click on color box should open a form which is indeed in another file.
This is successfully calling a function on the click event:
onClick={()=>{editpage(item.id)}}
But what does that function do? Absolutely nothing:
const editpage=(id)=>{ <Edit id={id}></Edit> }
The function doesn't return anything (not that returning from a click handler does anything either of course), doesn't perform any operations, nothing. It's just a single JSX expression.
Take a different approach entirely. Add your component to the markup, but wrap it in a condition based on state. For example, consider this state value:
const [openEditPage, setOpenEditPage] = useState();
The purpose of this state value is to keep track of which item.id should currently have its "edit" component visible. (Default to undefined so none are visible by default.)
Use this value when rendering the components:
<div id='color' className='div2' key={item.id} style={/*...*/} onClick={()=>{editpage(item.id)}}>
{openEditPage === item.id ? <Edit id={item.id}></Edit> : null}
</div>
So in this case the <Edit> component will only be rendered if openEditPage === item.id. Which is what the editpage() function can do:
const editpage = id => setOpenEditPage(id);
Clicking on the <div> would invoke the editpage function, which updates the state value, which triggers a re-render, and in the new render the <Edit> component is shown because the condition would be true.

React change class of component without using state

How can I change the className or style of a div without using state or any third party libraries? Lets say I click on a button, and I need to change the background color of a div how can I do that?
<Affix onChange={() => change css or class} offsetTop={60}>
<div>...</div> // Change css of this div
</Affix>
You can change any attribute or property of a Component (Element) in React by using basic javascript functions.
onClick={(e) => {
e.currentTarget.setAttribute("src", newUrl);
}
Will change an image the moment you click on it, without using Ref or State.
event.currentTarget will give you the reference to the component that fired that particular React.MouseEventHandler event, and with the Element's reference, you can manipulate it at will.
This is particularly useful when you need to change an attribute in a component in a map loop without needing to keep track of it.
Edit:
A friend of mine just gave me a better one for classes in specific:
e.currentTarget.classList.add('my_custom_klass')
You can either do it manually using state:
const [myClass, setMyClass] = useState('bgColor-white');
return (
<Affix onChange={() => setMyClass('bgColor-black')} offsetTop={60}>
<div className={myClass}>...</div> // Change css of this div
</Affix>
)
Or you can use a library that handles dynamic styling. I use and recommend styled-components

How do I make a selected radio button change one piece of state based upon another radio button changing another piece of state?

I have a couple of components I am building and have run into a bit of a stumbling block.
The components start with a piano keyboard on which I can overlay different musical entities, like notes, intervals, chords, scales, etc...by passing the note names via a notes={[]} array prop into the Keyboard component. In this particular instance of the component I am then importing it into a Scales component in which I have added scale and note buttons, so I can overlay entire scales in this instance on top of the keyboard, which is all basically working. have a list of note names that I can click on and then overlay that scale on top of the keyboard, like so:
The gif shows the current behavior of the Scales component, which is not quite correct yet...
In the gif you can see that the major and minor scale buttons change the state of the scale, which is then used by the note name buttons to change the state of the keyboard beneath it. But what I also want it to do is switch the currently selected scale when the major or minor button is clicked, but currently the note name buttons don't automatically react to the change in state in the major and minor buttons, but have to be clicked again to make the change occur.
What I want is to be able to just click the major and minor buttons and which ever note is selected will simply change from major to minor without having to re-click the selected scale note again, which is the current behavior.
So, in my Scales component I am using custom radio buttons like so, first to control the major and minor buttons:
<MajorInput
type="radio"
name="scale"
id="major"
label="major"
value="major"
checked={scale === 'major'}
onChange={handleChange}
onClick={() => setScale('major')}
/>
<MajorLabel
whileHover={{ scale: 1 }}
whileTap={{ scale: 0.9 }}
htmlFor="major"
>
Major
</MajorLabel>
...then to control the note buttons, like so:
<NoteInput
id="c"
scale={scale}
type="radio"
name="notes"
label="c"
value="c"
onClick={
() => setNotes(
scale === 'major' ? ['c1p', 'd1ma', 'e1ma', 'f1p', 'g1p', 'a1ma', 'b1ma'] :
scale === 'minor' ? ['c1p', 'd1ma', 'eb1mi', 'f1p', 'g1p', 'ab1mi', 'bb1mi'] :
''
)
}
/>
<NoteLabel
whileHover={{ scale: 1 }}
whileTap={{ scale: 0.9 }}
scale={scale}
htmlFor="c"
>
{
scale === 'major' ? 'C' :
scale === 'minor' ? 'C' :
'C'
}
</NoteLabel>
...and the state is established via two useState hooks, like so:
const [ scale, setScale] = useState('')
const [ notes, setNotes] = useState([])
...then ultimately the imported Keyboard component receives it's notes={notes} prop from the notes buttons, like so:
<Keyboard octaves={'2'} notes={notes}/>
...so i don't really know how I could make the note buttons be aware or know about the scale buttons being clicked and then translate that information to the keyboards notes prop, which is where i am stuck now...
Here is a code sandbox of the the component:
https://codesandbox.io/s/scales-981uk
Thank you for your help :-)
I looked through your code.
The problem you have right now is that your note components are not rerendered and restyled when the major button is clicked. In React, you can use the change in props to trigger a rerender which will also restyle your notes.
I would suggest to put all your note inputs into a sub component. :
// ./Scales.js
import NoteButtonBox from ./NoteButtonBox.js
//...
// important: pass scale as props.
// Everytime scale changes, the note buttons are rerendered and restyled
sub component
return (
<Container>
<ScaleButtonBox>
{/* ... */}
<ScaleButtonBox>
<NoteButtonBox scale={scale} />
{/* ... */}
// ./NoteButtonBox.js
const NoteButtonBox = ({scale}) => {
// Don't forget to also move 'const [notes, setNotes] = useState([]);' into the
const [notes, setNotes] = useState([]);
return {
/* return your styled notes based on props scale */
}
}
EDIT
For situations where you need to access state across multiple sub components, you can use React Context. Alternatively, you can use React Redux which accomplishes the same thing. I would suggest Comtext because it is a native part of React.
Breaking up your app into sub components might seem like unnecessary work but it is good practice to create many small components in React. React encourages composition like I suggest.
Create a NotesStateContext class.
You define the where it is needed NotesStateContext.Provider:
<NotesStateContext.Provider value="dark">
<NoteButtonBox />
</* All other components that need to access the state of your notes */>
</NotesStateContext.Provider>
Get and update your state from the provider

Mimic React custom component

I have a custom Reactjs component to display Pagination with next/previous buttons at the bottom of a grid. Now, the business needs to display the same component on top of the grid as well. How to display the previous /next button events based on the input provided in prev/next buttons at the bottom of the grid?
I tried using javascript innerHTML to mimic the behaviour. It works only with the display. It does not attach the event listener of the buttons. I tried even with
document.querySelector.addEventListener('click', ()=>{console.log('test')})
It does not work. Is there a better way to do with react.
I am going to just add some more content to Shmili Breuer answer.
If i understood you correctly you have 2 navigations, one at the top one at the bottom. The way you connect them would be through a state of you component, or a parent component if you are using functional component to render pagination stuff. So if you change the state it will reflect on both of your navigations. Also you can use only one function here, by passing a parameter, im gonna copy a code from before mentioned answer.
// first create a function
nextFunction = (condition) => {
if(condition){
this.setState(prevState=>({
page: prevState.page-1
}))
} else {
this.setState(prevState=>({
page: prevState.page+1
}))
}
}
// then use it in your button
<button onClick={() => this.nextFunction(some condition)}>Next</button>
Just put that component on top and bottom
<Grid>
<Pagination />
{...someOtherComponents}
<Pagination />
</Grid>
it's ok in react. Optimization that you want to do is overhead.
In react you would add an onClick attribute to an element you want to handle a click on.
Something like this
// first create a function
nextFunction = () => {
do next functionality....
}
// then use it in your button
<button onClick={() => this.nextFunction()}>Next</button>
This way you can have both top and bottom pagination call the same function.
Hope this helps

reusing stateful react components

I'm new to React and wanted some advice.
The problem is essentially thew following
I have a number of component buttons that open a modal, within this modal we have further buttons to offer a selection.
Home Screen Buttons (components)
<Button value="First"></button>
<Button value="Second"></button>
<Button value="Third"></button>.....
Modal.
<button value="Donald"></button>
<button value="Thomas"></button>
<button value="Evie"></button>.....
So the home screen buttons for example would have the following function, that it would pass down to the modal buttons onClick attribute.
selectPerson(e) {
setState({ selection : e.target.value})
}
So by selecting "First", we choose a person, close the modal, tie the selected person with Buttons state, and then repeat for second and so on.
Essentially these Buttons to open the modal have the same core functions (state and props). i.e I could have a template component an reuse it, but I would like each component to have independent state and props.
So I can achieve what I need but I've written each home screen button as an independent component, that is I've written a lot of the same code. If I attempt to reuse the SAME component, the are treated as the same component, and selecting a person changes all buttons state.
Is there anyway to avoid rewriting the same code for each (I have twenty). I've only just started (obviously) and am not too familiar with some of the more advanced concepts. If anyone has any suggestions or further questions, it would be great. I haven't provided code as the code works, its just extremely bulky
Yeah sure, define the button components and hand down certain elements inside its props.
You can then setState to be these handed down prop elements etc etc.
So define a button component with its various states defined by the props you hand it down. Then you have a mutable template Button component.
When you render these you just define its props.
<Button prop = "First" prop2 = "EXAMPLE"..../>
<Button prop = "Second" prop2 = "EXAMPLE2"..../>
<Button prop = "Third" prop2 = "EXAMPLE3"..../>
then inside the Button component use something like
this.state { property1 : this.props.prop, property2 : this.props.prop2 ...}
Hope this helps! I've recently been doing something similar

Resources