REACT - onclick sınıfı aç / kapat


93

onClickCSS özelliklerini değiştirmek için aktif bir sınıfı nasıl değiştireceğimi anlamaya çalışıyorum .

Pek çok yaklaşım aldım ve birçok SO cevabı okudum. Jquery kullanmak nispeten basit olurdu, ancak bunu react ile yapmayı çözemiyorum. Kodum aşağıda. Bunu nasıl yapmam gerektiğini kimse söyleyebilir mi?

Her öğe için yeni bir bileşen oluşturmadan bunu yapmak mümkün müdür?

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>
  }

}

Yanıtlar:


86

Durum kullanın. Reacts dökümanları burada .

class MyComponent extends Component {
    constructor(props) {
        super(props);
        this.addActiveClass= this.addActiveClass.bind(this);
        this.state = {
            active: false,
        };
    }
    toggleClass() {
        const currentState = this.state.active;
        this.setState({ active: !currentState });
    };

    render() {
        return (
            <div 
                className={this.state.active ? 'your_className': null} 
                onClick={this.toggleClass} 
            >
                <p>{this.props.text}</p>
            </div>
        )
  }
}

class Test extends Component {
    render() {
        return (
            <div>
                <MyComponent text={'1'} />
                <MyComponent text={'2'} />
            </div>
        );
    }
}

3
Bunu fazladan bir bileşen oluşturmadan yapmanın bir yolu var mı?
peter flanagan

2
Karmaşık bileşenleri daha küçük bileşenlere ayırmak istiyorsunuz, bkz. Facebook.github.io/react/docs/…
cssko

1
Bileşeni parçaladım, ancak bu yine activede tıklandığında her bir öğeye eklenir . Sadece bir elementin aktif bir sınıfa sahip olmasını istiyorum
Peter Flanagan

1
Bu, geçişli 'aktif' sınıf olarak adlandırılamaz çünkü diğer elemanların aktif sınıfları hala orada.
Dat TT

6
Lütfen yanıtı onClicktüm küçük harflerin aksine yanlış olarak kullanacak şekilde günceller misiniz
peter flanagan

24

Satır içi if ifadesinde "&&" operatörünü kullanmayı tercih ederim. Benim düşünceme göre bu şekilde daha temiz bir kod tabanı veriyor.

Genelde böyle bir şey yapabilirsiniz

render(){
return(
  <div>
    <button className={this.state.active && 'active'}
      onClick={ () => this.setState({active: !this.state.active}) }>Click me</button>
  </div>
)
}

Ok işlevinin ES6 özelliği olduğunu unutmayın ve sınıf yapıcısında () 'this.state.active' değerini ayarlamayı unutmayın {}

this.state = { active: false }

veya JSX'e css enjekte etmek istiyorsanız, bu şekilde yapabilirsiniz

<button style={this.state.active && style.button} >button</button>

ve stil json değişkeni tanımlayabilirsiniz

const style = { button: { background:'red' } }

JSX stil sayfalarında camelCase kullanmayı unutmayın.


2
Bileşenler üzerinde basit sınıf adlarını değiştirmenin en akıllı yolu budur.
SeaWarrior404

11

AddActiveClass'ınızın neye tıklandığını bilmesi gerekiyor. Bunun gibi bir şey işe yarayabilir (div'lerin bir durum dizisi olarak etkin olduğu bilgileri eklediğime ve onClick'in artık bir parametre olarak tıklanan bilgiyi ilettiğine ve ardından durumun buna göre güncellendiğine dikkat edin - kesinlikle daha akıllı yollar vardır. yap ama fikri anladın).

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>
    );
  }
}

9

Bunu kancalarla da yapabilirsiniz .

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>
   );
}  

4

React kullanarak herhangi bir id / elemente geçiş sınıfı ekleyebilirsiniz, deneyin

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>
    )
    }
......

Buna, "isActive" ifadelerinin her biri için tanımlamak istemediğiniz statik bir sınıfınız varsa aşağıdaki kod stilini kullanabileceğinizi de eklemek isterim:className={`left-panel ${this.state.isActive===true ? 'leftbar-open' : 'leftbar-close'}`}
Zeliax

4

React, bileşen durumu kavramına sahiptir, bu nedenle değiştirmek istiyorsanız, şunu yapın setState:

constructor(props) {
  super(props);

  this.addActiveClass= this.addActiveClass.bind(this);
  this.state = {
    isActive: false
  }
}

addActiveClass() {
  this.setState({
    isActive: true
  })
}

Bileşeninizde this.state.isActiveihtiyacınız olanı oluşturmak için kullanın .

Durum 1'i bileşen # 2'de ayarlamak ve onu bileşen # 2'de kullanmak istediğinizde bu daha karmaşık hale gelir. Tek yönlü veri akışına tepki vermek ve muhtemelen onu idare etmenize yardımcı olacak yeniden düzenlemek için daha fazlasını kazın.


Anlıyorum stateama bu, bir öğeye tıklandığında sınıf adının nasıl güncelleneceğini hala açıklamıyor
peter flanagan

jsx işaretlemenizde - <div className={this.state.isActive ? 'active' : ''}>. Koşullu oluşturma hakkında, ancak yine de duruma dayanır.
dhorelik

ancak bu, tıklandığında her öğeye etkin sınıfı ekleyecektir. Sadece tıklanan öğenin activesınıf adına sahip olmasını istiyorum
peter flanagan

2
neden her öğe? Sınıfı, koşulunu eklediğiniz öğeye ekler. İdeal olarak, öğeleriniz Itembileşene soyutlanmalıdır . Daha sonra bunu 3 kez dahil edeceksiniz ve temelde her biri kendi isActivedurumuna sahip 3 öğe alacaksınız . Demek istediğin bu mu?
dhorelik

onu bir Itembileşene bölmeden bunu yapmanın bir yolu var mı?
peter flanagan


2

İyi bir örnek olayları daha iyi anlamaya yardımcı olur:

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; 
}

React kodu

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"));

2

tıklama ile geçiş sınıfı veya geçiş durumu ekleyebilirsiniz

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>
  }

}

2

Doğru cevabı verdiği için @cssko'ya teşekkürler, ancak kendiniz denediyseniz, işe yaramadığını anlayacaksınız. @Matei Radu tarafından bir öneri yapıldı, ancak @cssko tarafından reddedildi, bu nedenle kod geri alınamaz olarak kaldı ('Tanımlanmamış özellik bağını okuyamıyor' hatasını verir). Aşağıda çalışan doğru cevap verilmiştir:

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>


1

Yakın zamanda React'i öğrenmeye başladım ve bilgimin ne kadar ileri gittiğini görmek için bir sekme oluşturmak istedim. Bununla karşılaştım ve redux olmadan bir şey uygulamaya karar verdim. Cevapların operasyonun neyi başarmak istediğini yansıtmadığını hissediyorum. Sadece bir aktif bileşen istiyor, ancak buradaki cevaplar tüm bileşenleri aktif hale getirecek. Bir şans verdim.

Aşağıda bir sekme dosyası var

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;

Sekmeler dosyası ...

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;

dizin dosyanız ...

import React from 'react';
import ReactDOM from 'react-dom';
import Tabs from './components/tabs';


ReactDOM.render(
    <Tabs />
  , document.querySelector('.container'));

ve css

.tab-bar {
    margin: 10px 10px;
    border: 1px solid grey;
}

.active-tab {
    border-top: 1px solid red;
}

Bu, üzerinde geliştirmek istediğim bir şeyin iskeletidir, bu nedenle tabNumber'ı 4'ün üzerine çıkarmak css'i bozacaktır.


1

İşte bulduğum bir kod:

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>
        );
    };
};

1

React'in bir bileşen durumu kavramı vardır, bu nedenle Değiştirmek istiyorsanız setState'i kullanın:

  1. App.js
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;
  1. bileşenler / TestState.js
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;
  1. Çıktı

görüntü açıklamasını buraya girin


0

Sadece yaklaşımımı eklemek istedim. Kancaları ve bağlam sağlayıcıyı kullanma.

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
}

Hızlı çalışır ve redux'un yerini alır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.