J'essaie de comprendre comment basculer une classe active onClick
pour modifier les propriétés CSS.
J'ai adopté de nombreuses approches et lu de nombreuses réponses SO. En utilisant jquery, ce serait relativement simple, cependant, je ne parviens pas à le faire avec react. Mon code est ci-dessous. Quelqu'un peut-il conseiller comment je dois faire cela?
Sans créer un nouveau composant pour chaque élément, est-il possible de faire cela?
class Test extends Component(){
constructor(props) {
super(props);
this.addActiveClass= this.addActiveClass.bind(this);
}
addActiveClass() {
//not sure what to do here
}
render() {
<div>
<div onClick={this.addActiveClass}>
<p>1</p>
</div>
<div onClick={this.addActiveClass}>
<p>2</p>
</div>
<div onClick={this.addActiveClass}>
<p>3</p>
</div>
</div>
}
}
javascript
reactjs
Peter Flanagan
la source
la source
active
à chaque élément au clic. Je ne veux qu'un seul élément pour avoir une classe activeonClick
par opposition à toutes les minuscules car vous avez incorrectementJe préférerais utiliser "&&" -operator sur l'instruction if en ligne. À mon avis, cela donne une base de code plus propre de cette façon.
En général, vous pourriez faire quelque chose comme ça
render(){ return( <div> <button className={this.state.active && 'active'} onClick={ () => this.setState({active: !this.state.active}) }>Click me</button> </div> ) }
Gardez simplement à l'esprit que la fonction de flèche est une fonctionnalité ES6 et n'oubliez pas de définir la valeur 'this.state.active' dans la classe constructor () {}
this.state = { active: false }
ou si vous souhaitez injecter du CSS dans JSX, vous pouvez le faire de cette façon
<button style={this.state.active && style.button} >button</button>
et vous pouvez déclarer la variable json de style
const style = { button: { background:'red' } }
n'oubliez pas d'utiliser camelCase sur les feuilles de style JSX.
la source
Eh bien, votre addActiveClass doit savoir ce qui a été cliqué. Quelque chose comme ça pourrait fonctionner (notez que j'ai ajouté les informations sur les divs actifs en tant que tableau d'état, et que onClick transmet maintenant les informations sur lesquelles on a cliqué en tant que paramètre, après quoi l'état est mis à jour en conséquence - il existe certainement des moyens plus intelligents de faites-le, mais vous avez l'idée).
class Test extends Component(){ constructor(props) { super(props); this.state = {activeClasses: [false, false, false]}; this.addActiveClass= this.addActiveClass.bind(this); } addActiveClass(index) { const activeClasses = [...this.state.activeClasses.slice(0, index), !this.state.activeClasses[index], this.state.activeClasses.slice(index + 1)].flat(); this.setState({activeClasses}); } render() { const activeClasses = this.state.activeClasses.slice(); return ( <div> <div className={activeClasses[0]? "active" : "inactive"} onClick={() => this.addActiveClass(0)}> <p>0</p> </div> <div className={activeClasses[1]? "active" : "inactive"} onClick={() => this.addActiveClass(1)}> <p>1</p> </div> <div onClick={() => this.addActiveClass(2)}> <p>2</p> </div> </div> ); } }
la source
Vous pouvez également le faire avec des crochets .
function MyComponent (props) { const [isActive, setActive] = useState(false); const toggleClass = () => { setActive(!isActive); }; return ( <div className={isActive ? 'your_className': null} onClick={toggleClass} > <p>{props.text}</p> </div> ); }
la source
en utilisant React, vous pouvez ajouter une classe à bascule à n'importe quel identifiant / élément, essayez
style.css
.hide-text{ display: none !important; /* transition: 2s all ease-in 0.9s; */ } .left-menu-main-link{ transition: all ease-in 0.4s; } .leftbar-open{ width: 240px; min-width: 240px; /* transition: all ease-in 0.4s; */ } .leftbar-close{ width: 88px; min-width:88px; transition: all ease-in 0.4s; }
fileName.js
...... ToggleMenu=()=>{ this.setState({ isActive: !this.state.isActive }) console.log(this.state.isActive) } render() { return ( <div className={this.state.isActive===true ? "left-panel leftbar-open" : "left-panel leftbar-close"} id="leftPanel"> <div className="top-logo-container" onClick={this.ToggleMenu}> <span className={this.state.isActive===true ? "left-menu-main-link hide-from-menu" : "hide-text"}>Welcome!</span> </div> <div className="welcome-member"> <span className={this.state.isActive===true ? "left-menu-main-link hide-from-menu" : "hide-text"}>Welcome<br/>SDO Rizwan</span> </div> ) } ......
la source
className={`left-panel ${this.state.isActive===true ? 'leftbar-open' : 'leftbar-close'}`}
React a un concept d'état des composants, donc si vous voulez le changer, faites un
setState
:constructor(props) { super(props); this.addActiveClass= this.addActiveClass.bind(this); this.state = { isActive: false } } addActiveClass() { this.setState({ isActive: true }) }
Dans votre composant, utilisez
this.state.isActive
pour rendre ce dont vous avez besoin.Cela devient plus compliqué lorsque vous souhaitez définir l'état dans le composant n ° 1 et l'utiliser dans le composant n ° 2. Il suffit de creuser davantage dans le flux de données unidirectionnel et éventuellement le redux qui vous aidera à le gérer.
la source
state
mais cela n'explique toujours pas vraiment comment mettre à jour le nom de la classe lorsqu'un élément est cliqué<div className={this.state.isActive ? 'active' : ''}>
. Il s'agit de rendu conditionnel, mais repose toujours sur l'état.active
nom de la classeItem
composant. Vous l'incluerez ensuite 3 fois et aurez essentiellement 3 éléments, chacun ayant son propreisActive
état. C'est ce que tu veux dire?Item
composant, y a-t-il un moyen de le faire?Les réponses ci-dessus fonctionneront, mais juste au cas où vous voudriez une approche différente, essayez classname: https://github.com/JedWatson/classnames
la source
Un bon échantillon aiderait à mieux comprendre les choses:
HTML
<div id="root"> </div>
CSS
.box { display: block; width: 200px; height: 200px; background-color: gray; color: white; text-align: center; vertical-align: middle; cursor: pointer; } .box.green { background-color: green; }
Code de réaction
class App extends React.Component { constructor(props) { super(props); this.state = {addClass: false} } toggle() { this.setState({addClass: !this.state.addClass}); } render() { let boxClass = ["box"]; if(this.state.addClass) { boxClass.push('green'); } return( <div className={boxClass.join(' ')} onClick={this.toggle.bind(this)}>{this.state.addClass ? "Remove a class" : "Add a class (click the box)"}<br />Read the tutorial <a href="http://www.automationfuel.com" target="_blank">here</a>.</div> ); } } ReactDOM.render(<App />, document.getElementById("root"));
la source
vous pouvez ajouter une classe de bascule ou un état de bascule en cliquant sur
class Test extends Component(){ state={ active:false, } toggleClass() { console.log(this.state.active) this.setState=({ active:true, }) } render() { <div> <div onClick={this.toggleClass.bind(this)}> <p>1</p> </div> </div> } }
la source
Merci à @cssko pour avoir fourni la bonne réponse, mais si vous l'avez essayé vous-même, vous vous rendrez compte que cela ne fonctionne pas. Une suggestion a été faite par @Matei Radu, mais a été rejetée par @cssko, donc le code reste impossible (il lancera l'erreur 'Impossible de lire la liaison de propriété d'undefined'). Voici la bonne réponse:
class MyComponent extends React.Component { constructor(props) { super(props); this.addActiveClass = this.addActiveClass.bind(this); this.state = { active: false, }; } addActiveClass() { const currentState = this.state.active; this.setState({ active: !currentState }); }; render() { return ( < div className = { this.state.active ? 'your_className' : null } onClick = { this.addActiveClass } > < p > { this.props.text } < /p> < / div > ) } } class Test extends React.Component { render() { return ( < div > < MyComponent text = { 'Clicking this will toggle the opacity through css class' } /> < / div > ); } } ReactDOM.render( < Test / > , document.body );
.your_className { opacity: 0.3 }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>
la source
J'ai commencé à apprendre React récemment et je voulais créer un onglet juste pour voir jusqu'où mes connaissances sont allées. Je suis tombé sur cela et j'ai décidé de mettre en œuvre quelque chose sans redux. J'ai l'impression que les réponses ne reflètent pas ce que l'OP veut réaliser. Il ne veut qu'un seul composant actif, mais les réponses ici définiront tous les composants actifs. Je lui ai donné une chance.
Ci-dessous un fichier onglet
import React, { Component } from 'react'; class Tab extends Component { render(){ const tabClassName = "col-xs-3 tab-bar"; const activeTab = this.props.activeKey === this.props.keyNumber ? "active-tab" : null; return ( <div className = {`${tabClassName} ${activeTab}`} onClick={()=>this.props.onClick(this.props.keyNumber)} > I am here </div> ); } } export default Tab;
Le fichier des onglets ...
import React, { Component } from 'react'; import Tab from './tab'; class Tabs extends Component { constructor(props){ super(props); this.state = { currentActiveKey: 0, tabNumber: 2 }; this.setActive = this.setActive.bind(this); this.setTabNumber = this.setTabNumber.bind(this); } setTabNumber(number){ this.setState({ tabNumber: number }); } setActive (key){ this.setState({ currentActiveKey: key }); } render(){ let tabs = []; for(let i = 0; i <= this.state.tabNumber; i++){ let tab = <Tab key={i} keyNumber={i} onClick={this.setActive} activeKey={this.state.currentActiveKey}/>; tabs.push(tab); } return ( <div className="row"> {tabs} </div> ); } } export default Tabs;
votre fichier d'index ...
import React from 'react'; import ReactDOM from 'react-dom'; import Tabs from './components/tabs'; ReactDOM.render( <Tabs /> , document.querySelector('.container'));
et le css
.tab-bar { margin: 10px 10px; border: 1px solid grey; } .active-tab { border-top: 1px solid red; }
Ceci est un squelette de quelque chose que je veux améliorer, donc augmenter le tabNumber au-delà de 4 cassera le css.
la source
Voici un code que j'ai trouvé:
import React, {Component} from "react"; import './header.css' export default class Header extends Component{ state = { active : false }; toggleMenuSwitch = () => { this.setState((state)=>{ return{ active: !state.active } }) }; render() { //destructuring const {active} = this.state; let className = 'toggle__sidebar'; if(active){ className += ' active'; } return( <header className="header"> <div className="header__wrapper"> <div className="header__cell header__cell--logo opened"> <a href="#" className="logo"> <img src="https://www.nrgcrm.olezzek.id.lv/images/logo.svg" alt=""/> </a> <a href="#" className={className} onClick={ this.toggleMenuSwitch } data-toggle="sidebar"> <i></i> </a> </div> <div className="header__cell"> </div> </div> </header> ); }; };
la source
React a un concept d'état des composants, donc si vous voulez basculer, utilisez setState:
import React from 'react'; import TestState from './components/TestState'; class App extends React.Component { render() { return ( <div className="App"> <h1>React State Example</h1> <TestState/> </div> ); } } export default App;
import React from 'react'; class TestState extends React.Component { constructor() { super(); this.state = { message: 'Please subscribe', status: "Subscribe" } } changeMessage() { if (this.state.status === 'Subscribe') { this.setState({message : 'Thank You For Scubscribing.', status: 'Unsubscribe'}) } else { this.setState({ message: 'Please subscribe', status: 'Subscribe' }) } } render() { return ( <div> <h1>{this.state.message}</h1> <button onClick={()=> this.changeMessage() } >{this.state.status}</button> </div> ) } } export default TestState;
la source
Je voulais juste ajouter mon approche. Utilisation de hooks et de fournisseur de contexte.
Nav.js
function NavBar() { const filterDispatch = useDispatchFilter() const {filter} = useStateFilter() const activeRef = useRef(null) const completeRef = useRef(null) const cancelRef = useRef(null) useEffect(() => { let activeClass = ''; let completeClass = ''; let cancelClass = ''; if(filter === ACTIVE_ORDERS){ activeClass='is-active' }else if ( filter === COMPLETE_ORDERS ){ completeClass='is-active' }else if(filter === CANCEL_ORDERS ) { cancelClass='is-active' } activeRef.current.className = activeClass completeRef.current.className = completeClass cancelRef.current.className = cancelClass }, [filter]) return ( <div className="tabs is-centered"> <ul> <li ref={activeRef}> <button className="button-base" onClick={() => filterDispatch({type: 'FILTER_ACTIVE'})} > Active </button> </li> <li ref={completeRef}> <button className="button-base" onClick={() => filterDispatch({type: 'FILTER_COMPLETE'})} > Complete </button> </li> <li ref={cancelRef}> <button className={'button-base'} onClick={() => filterDispatch({type: 'FILTER_CANCEL'})} > Cancel </button> </li> </ul> </div> ) } export default NavBar
filterContext.js
export const ACTIVE_ORDERS = [ "pending", "assigned", "pickup", "warning", "arrived", ] export const COMPLETE_ORDERS = ["complete"] export const CANCEL_ORDERS = ["cancel"] const FilterStateContext = createContext() const FilterDispatchContext = createContext() export const FilterProvider = ({ children }) => { const [state, dispatch] = useReducer(FilterReducer, { filter: ACTIVE_ORDERS }) return ( <FilterStateContext.Provider value={state}> <FilterDispatchContext.Provider value={dispatch}> {children} </FilterDispatchContext.Provider> </FilterStateContext.Provider> ) } export const useStateFilter = () => { const context = useContext(FilterStateContext) if (context === undefined) { throw new Error("place useStateMap within FilterProvider") } return context } export const useDispatchFilter = () => { const context = useContext(FilterDispatchContext) if (context === undefined) { throw new Error("place useDispatchMap within FilterProvider") } return context } export const FilterReducer = (state, action) => { switch (action.type) { case "FILTER_ACTIVE": return { ...state, filter: ACTIVE_ORDERS, } case "FILTER_COMPLETE": return { ...state, filter: COMPLETE_ORDERS, } case "FILTER_CANCEL": return { ...state, filter: CANCEL_ORDERS, } } return state }
Fonctionne rapidement et remplace redux.
la source