ReactJs changing css property onclick - css

I made a variable that has the style which I would want the input box to change to when it is clicked on.
How can I implement it so that when the input box is clicked, the border color of the input box changes to blue, considering that CSS, styles and everything else are imported?
const inputStyle = css
border-color: blue;
;
const InputBox = styled.input
myClick: function () {
inputstyle
}
;
render() {
return (
<InputBox
placeholder='Click Me'
type='text'
onClick={this.myClick}
/>

styled.foo doesn't return a class component, so writing methods as if they're on a class in the template string won't work.
Since you're handling something stateful (was this thing clicked?) you need to have some place to put that state. Then you can pass that state to the InputBox component:
const InputBox = styled.input`
border-color: ${({ clicked }) => clicked ? 'blue' : 'transparent'};
`
class Parent extends React.Component {
constructor (props) {
this.state = { clicked: false }
}
handleClick () {
this.setState({ clicked: true })
}
render () {
return (
<InputBox
placeholder="Click Me"
type="text"
clicked={this.state.clicked}
onClick={this.handleClick}
/>
)
}
}
I'd suggest checking out the "Passed Props" section of the styled-components docs.

you can do this :
const Styles = {
inputNormal:{color:'blue'},
inputClicked:{color:'red'}
}
class Parent extends React.Component {
constructor (props) {
this.state = { clicked: false }
}
handleClick () {
this.setState({ clicked: true })
}
render () {
return (
<InputBox
placeholder="Click Me"
type="text"
style={this.state.clicked?styles.inputNormal:styles.inputClicked}
onClick={this.handleClick}
/>
)}}

You should add styles with variables like this:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
clicked: false
};
}
myClick = () => {
this.setState({
clicked: true
});
};
render() {
const inputStyle = {
borderColor: "blue"
};
return (
<input
placeholder="Click Me"
type="text"
onClick={this.myClick}
style={this.state.clicked ? inputStyle : null}
/>
);
}
}
Here is a working demo:
DEMO

Related

Changing CSS styles when an event fires

I'm trying to integrate THEOPlayer in my project and I want to customize styles depending on certain events. For instance, I would love to hide the toolbar and show an overlay image when the video is paused.
They do expose some CSS classes that I can change manually but my question is, how do I change the values in CSS on a specific event. Since the player is imported as a single JSX element I don't know how to add custom classes to its specific parts. So I would like to know if there is another way.
Here is a component where an instance of Player is created:
class Player extends React.Component {
_player = null;
_el = React.createRef();
componentDidMount() {
const { source, onPlay, onPause } = this.props;
if (this._el.current) {
this._player = new window.THEOplayer.Player(this._el.current, {
libraryLocation:
"https://cdn.myth.theoplayer.com/7aff3fa6-f92e-45f9-a40e-1bce9911b073/",
});
this._player.source = source;
this._player.addEventListener("play", onPlay);
this._player.addEventListener("pause", onPause);
}
}
componentWillUnmount() {
if (this._player) {
this._player.destroy();
}
}
render() {
return (
<div
className={
"theoplayer-container video-js theoplayer-skin vjs-16-9 THEOplayer"
}
ref={this._el}
>
</div>
);
}
}
export default Player;
And that's a part of code where I want to change styles onPlay and onPause
<div className={"player-container"}>
<Player
source={source}
onPlay={() => {
console.log("playing");
}}
onPause={() => {
console.log("paused");
}}
/>
</div>
Use like this
state = {
play: false,
pause: true,
}
const playFn = () => {
this.setState = ({
play: true,
pause: false,
})
}
const pauseFn = () => {
this.setState = ({
play: false,
pause: true,
})
}
<div className={"player-container"}>
<Player
source={source}
onPlay={playFn}
onPause={pauseFn}
activatePlayClasses={play}
activatePauseClasses={pause}
bg={'https://example/example.jpg'}
/>
</div>
// on Player component
const { source, onPlay, onPause, activatePauseClasses, activatePlayClasses , bg} = this.props;
render() {
return (
<div
className={
`theoplayer-container video-js theoplayer-skin vjs-16-9 THEOplayer
${activatePauseClasses ? 'your pause class' : ''}
${activatePlayClasses ? 'your play class' : ''}`
}
style={{backgroundImage: `url(${bg})`}}
ref={this._el}
>
</div>
);
}
I have updated code

Calling a function from another component with redux

Trying to toggle open a modal from another component with redux. Almost there but not really sure how to finish it up - been looking around for a clear answer!
On the HomeScreen component (the main component), to activate the openModal method on the AddCircleModal component, causing the Modal to open.
The Modal - AddCircleModal: Using redux, I can successfully close the modal if I open it manually in the code
class AddCircleModal extends React.Component {
state = {
top: new Animated.Value(screenHeight),
modalVisible: false
}
// componentDidMount() {
// this.openModal()
// }
openModal = () => {
Animated.spring(this.state.top, {
toValue: 174
}).start()
this.setState({modalVisible: true})
}
closeModal = () => {
Animated.spring(this.state.top, {
toValue: screenHeight
}).start()
this.setState({modalVisible: false})
}
render() {
return (
<Modal
transparent={true}
visible={this.state.modalVisible}
>
<AnimatedContainer style={{ top: this.state.top, }}>
<Header />
<TouchableOpacity
onPress={this.closeModal}
style={{ position: "absolute", top: 120, left: "50%", marginLeft: -22, zIndex: 1 }}
>
<CloseView style={{ elevation: 10 }}>
<FeatherIcon name="plus" size={24} />
</CloseView>
</TouchableOpacity>
<Body />
</AnimatedContainer>
</Modal>
)
}
}
function mapStateToProps(state) {
return { action: state.action }
}
function mapDispatchToProps(dispatch) {
return {
closeModal: () =>
dispatch({
type: "CLOSE_MODAL"
})
}
}
export default connect(mapStateToProps, mapDispatchToProps)(AddCircleModal)
HomeScreen: The other component that I want to toggle from
//redux
import { connect } from 'react-redux'
import styles from './Styles'
class HomeScreen extends React.Component {
constructor() {
super();
this.state = {
};
}
toggleOpenCircleModal = () => {
// this.openModal() - what do I do with this to call the openModal function in the modal component?
console.log('owwwww weeeee')
}
render() {
return (
<SafeAreaView>
<HomeHeader openModal={this.toggleOpenCircleModal}/> - this method is because I'm calling toggleOpenCircleModal from a button in the header of the home screen. It works as it outputs the 'owwwww weeeee' string to the console.
<SafeAreaView style={{ width: '100%', flex: 1}} />
<AddCircleModal />
</SafeAreaView>
);
}
}
function mapStateToProps(state) {
return { action: state.action }
}
function mapDispatchToProps(dispatch) {
return {
openModal: () =>
dispatch({
type: "OPEN_MODAL"
})
}
}
export default connect(mapStateToProps, mapDispatchToProps)(HomeScreen)
modalToggle: The reducer
const initialState = {
action: ""
}
const modalToggle = (state = initialState, action) => {
switch (action.type) {
case "OPEN_MODAL":
return { ...state, action: "openModal" }
case "CLOSE_MODAL":
return { ...state, action: "closeModal" }
default:
return state
}
}
export default modalToggle
Right now, your components are not using redux store properly.
When you use mapStateToProps, you can access every redux store reducer. You can access every prop in them and these will be sent via props in your connected component. For instance:
//redux
import { connect } from 'react-redux'
import styles from './Styles'
class HomeScreen extends React.Component {
constructor() {
super();
this.state = {
};
}
toggleOpenCircleModal = () => {
if(this.props.action === 'openModal') {
this.props.openModal();
} else {
this.props.closeModal();
}
}
render() {
const { action } = this.props; // this.props.action is coming from Redux Store
return (
<SafeAreaView>
{action} // this will be 'openModal'
</SafeAreaView>
);
}
}
function mapStateToProps(state) {
return { action: state.action } // this will be available in HomeScreen as props.action
}
function mapDispatchToProps(dispatch) {
return {
openModal: () =>
dispatch({
type: "OPEN_MODAL"
})
}
}
export default connect(mapStateToProps, mapDispatchToProps)(HomeScreen)
You can read more on https://react-redux.js.org/using-react-redux/connect-mapstate.
The same goes for mapDispatchToProps. In your case, openModal will be available in props.openModal in your HomeScreen component. You can read more on https://react-redux.js.org/using-react-redux/connect-mapdispatch
Based on this, in your AddCircleModal component, you should be using props.action to evaluate if the modal should be visible. (props.action === 'openModal').
If you want to open or close your modal, you'll just need to call the openModal or closeModal dispatch call in your component. In HomeScreen component, in your function toggleOpenCircleModal, you will call openModal() or closeModal() depending on props.action === 'openModal'.
Lastly, you should be using just a boolean value to check for the modal visibility, instead of a string, if that's the only purpose for your reducer.
const initialState = false;
const modalToggle = (state = initialState, action) => {
switch (action.type) {
case "OPEN_MODAL":
return true;
case "CLOSE_MODAL":
return false;
default:
return state
}
}
export default modalToggle

Updating styles of a styled-component on props change slow?

In my parent component i have a onScroll Listener that determines whether i hit a specific point when scrolling. There is a boolean stored in the state. I pass this state variable down to a child. In that child i have a styled component that changes with the boolean state variable that was passed down as props. When i scroll really fast the css seems to change very slow. Is there anyway to speed this up?
Parent Component:
class Parent extends Component {
constructor(props) {
super(props);
this.state = {
flag: false
}
}
componentDidMount() {
var test = ReactDOM.findDOMNode(this.refs.test);
test.addEventListener('scroll', this.handleScroll);
}
handleScroll = () => {
if (test.scrollTop = 10) {
this.setState({
flag: true
})
} else {
this.setState({
flag: false
})
};
}
render() {
return (
<Component ref="test" >
<Child flag={
this.state.flag
}/>
</Component>
)
}
}
Child Component:
const Container = styled.div`
height: ${({flag})=>flag ? "10px" : "50px"}
`;
....
....
....
render(){
<Container flag={this.props.flag}/>
}
that is a very basic idea of what im doing in general, when i scroll really fast past the point of trigger it takes a slight second before rendering. Is there anyway i can avoid this delay and speed things up. Or is there a better way you guys recommend doing this.
In handleScroll method, you doesn't declare test. You should do like the following:
class Parent extends Component {
constructor(props) {
super(props);
this.state = {
flag: false
}
}
componentDidMount() {
var test = ReactDOM.findDOMNode(this.refs.test);
test.addEventListener('scroll', this.handleScroll);
}
handleScroll = (event) => {
if (event.scrollTop = 10) {
this.setState({
flag: true
})
} else {
this.setState({
flag: false
})
};
}
render() {
return (
<Component ref="test">
<Child flag={
this.state.flag
}/>
</Component>
)
}
}

Access Event Of Component That Is Passed As Prop

I pass a React Component as a Prop to a child.
That component has an event.
In child component, I want to get access to that event and bind it to a method inside child. How can I do that ?
I often use Semantic-UI React Modal as following:
class Example extends Component {
constructor(props) {
super(props);
this.state = {
modalOpen: false
}
}
handleOpen = () => this.setState({ modalOpen: true })
handleClose = () => this.setState({ modalOpen: false })
render(){
return(
<Modal
onClose={this.handleClose}
open={this.state.modalOpen}
trigger={<Button onClick={this.handleOpen}>Gandalf</Button>}>
<Modal.Header>Balrog</Modal.Header>
<Modal.Content>
<h1>You shall not pass!</h1>
{/*
Some form that closes Modal on success
onSuccess : this.handleClose
*/}
<Button onClick={this.handleClose}>Grrrrr</Button>
</Modal.Content>
</Modal>
)
}
}
export default Example
Now I want to make it reusable
import React, { Component } from 'react'
import { Modal } from 'semantic-ui-react'
class ReusableModal extends Component {
constructor(props) {
super(props);
this.state = {
modalOpen: false
}
}
handleOpen = () => this.setState({ modalOpen: true })
handleClose = () => this.setState({ modalOpen: false })
render(){
return(
<Modal
onClose={() => this.handleClose}
open={this.state.modalOpen}
{/*
How to access onClick event on trigger prop content ?
this.prop.trigger can be a Button or a Menu.Item
*/}
{...this.props}>
{this.props.children}
</Modal>
)
}
}
How can I have access to the trigger prop Component and bind its onClick event to handleOpen method ?
Edit :
to be more precise here is what I'm looking for
<ChildComponent trigger={<Button>This button should fire a function defined in child component</Button>} />
ChildComponent extends Component {
functionToCall = () => { console.log('hello') }
// I would like to :
// let myButton = this.props.trigger
// myButton.onClick = functionToCall
}
In React, data flows from parent to child. If there are multiple child components that have events that need to trigger changes in parent component you must fire callback function in child component.
Parent component:
handleOpen = () => { // do something }
(...)
<childComponent onClickCallback={this.handleOpen}
And in child component:
<button onClick={this.props.onClickCallback}> Click to close</button>
Pass this.handleOpen as a prop and call it as a prop in child component, and it will trigger function in the parent component, where you can handle data however you want.
Is this what you asked for?
The key here is to clone element
ChildComponent extends Component {
functionToCall = () => { console.log('hello') }
this.Trigger = React.cloneElement(
this.props.trigger,
{ onClick: this.functionToCall }
)
}

React Radium - How to change property values dynamically

I want to dynamically change, say, the background color of the button dynamically.
If this is my radium js styles file:
button-styles.js
export const styles = {
base: {
backgroundColor: 'red',
}
};
button.js
const myStyles = require('./styles/button-styles.js');
#Radium
class MyButton extends Component {
render() {
{/*
How do I tell the button to override the default value
for background color of red, to the props value if it exists,
(and in this scenario it does and is the color green)?
*/}
return (<Button style={ ??? }>Click Me</Button>)
}
}
MyButton.defaultProps = {
btnBg: 'green'
}
MyButton.propTypes = {
btnBg: PropTYpes.string
}
(A side note to the powers that be; there is no react-radium tag.)
You could create your styles as a function of your props.
Advantage: You do not need to have the fetching algorithm which just basically assigns your styles.
button-styles.js
export default props => ({
backgroundColor: props.btnBg
// if you need a default value you could use
// props.btnBg || 'green'
})
// You could even use ES6 object destruction
export default ({btnBg}) => ({
backgroundColor: btnBg
})
button.js
const myStyles = require('./styles/button-styles.js');
#Radium
class MyButton extends Component {
render() {
return <Button style={ myStyles(this.props) }>Click Me</Button>
}
}
MyButton.defaultProps = {
btnBg: 'green'
}
MyButton.propTypes = {
btnBg: PropTypes.string
}
Don't know if this is proper way to do it, but this worked for me.
Default properties in base remained, while only those with a matching
prop name in the dynamicStyle prop object were affected. So in this
example color and fontSize were not affected and remained with the
return settings, with only backgroundColor now being green..
UPDATE:
Per Janaka Stevens recommendation, I made the settings immutable. But I did so in the fetchBtnStyle method and not a hard coding in the component per Janaka Stevens' idea (ie the color property), because I theorize I would have no clue what property the user may wish to change; the user may want to change color, font-size or background-color.
button-styles.js
const styleValues = {
base: {
fontSize: '1.0em',
color: '#fff',
backgroundColor: 'red',
}
};
module.exports = {
fetchBtnStyle(values) {
const settings = {};
// making the value immutable here <-------------
Object.assign(settings, styleValues.base)
if (values !== undefined) {
Object.assign(settings, values);
}
return settings;
}
};
button.js
import btnStyles = require('./styles/button-styles.js');
#Radium
class MyButton extends Component {
render() {
return (
<Button style={ btnStyles.fetchBtnStyle(this.props.dynamicStyle) }>
Click Me
</Button>)
}
}
MyButton.defaultProps = {
dynamicStyle: {
backgroundColor: 'green'
}
}
MyButton.propTypes = {
dynamicStyle: PropTypes.object
}
The style needs to be immutable so you will want to define it in the render like so.
class MyButton extends Component {
render() {
let btnSty = MyStyles.base;
if (this.props.dynamicSty)
btnSty.color = this.props.dynamicSty.color;
else
btnSty.color = MyStyles.base.color;
return (
<Button style={btnSty}>
Click Me
</Button>)
}
}

Resources