我如何能切换一个类点击与反应?

我试图找出如何切换一个活动类点击改变 CSS 属性。

我的代码在下面。有人能告诉我该怎么做吗?在不为每个项目创建新组件的情况下,是否可以做到这一点?

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


}
355473 次浏览

使用状态。请参阅 反应文件

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

您的 addActiveClass 需要知道点击了什么。类似这样的方法可以工作(注意,我已经添加了 div 作为状态数组处于活动状态的信息,onClick 现在将被点击的信息作为参数传递,之后状态会相应地更新——当然有更聪明的方法来做到这一点,但是你已经有了想法)。

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

React has a concept of components state, so if you want to switch it, do a setState:

constructor(props) {
super(props);


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


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

In your component use this.state.isActive to render what you need.

当您想要在组件 # 1中设置状态并在组件 # 2中使用它时,这会变得更加复杂。只需深入研究反应单向数据流,并可能减少这些数据流,就可以帮助您处理它。

The above answers will work, but just in case you want a different approach, try classname: https://github.com/JedWatson/classnames

I would prefer using the && operator in an inline if statement. In my opinion it gives cleaner codebase this way.

Generally you could be doing something like this:

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

Just keep in mind that arrow functions are and ES6 feature and remember to set this.state.active value in the class constructor.

this.state = { active: false }

或者,如果你想在 JSX 中注入 CSS,你可以这样做:

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

And you can declare style json variable:

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

记住在 JSX 样式表上使用 camelCase。

一个好的样本 将有助于更好地理解事物:

超文本标示语言

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

反应代码

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

可以单击添加 切换类或切换状态

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


}

I started learning React recently and wanted to build a tab just to see how far my knowledge has gone. I came across this and decided to implement something without redux. I kind of feel the answers don't reflect what op wants to achieve. He wants only one active component but the answers here will set all components active. I have given it a shot.

下面是一个制表符文件

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;

标签文件..。

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;

你的索引文件。

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




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

还有 CSS

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


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

这是我想要改进的一些东西的框架,因此将 tabNumber 增加到4以上会破坏 css。

使用 React 可以向任何 id/元素添加 toggle 类,请尝试

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

这是我想出来的一个代码:

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

感谢@cssko 提供了正确的答案,但是如果你自己尝试了,你会发现它不起作用。@ Matei Radu 提出了一个建议,但是@cssko 拒绝了,所以代码仍然不能运行(它会抛出错误‘ Can not read property bind of unDefinition’)。下面是工作正确答案:

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>

您也可以使用 钩子来完成这项工作。

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

React 有一个组件状态的概念,所以如果你想去 Toggle,使用 setState:

  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. 组件/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. 输出

enter image description here

只是想添加我的方法。使用钩子和上下文提供程序。

导航系统

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

过滤器上下文

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
}

工作迅速,并替代 redux。

You can simply access the element classList which received the click event using event.target then by using toggle method on the classList object to add or remove the intended class

<div onClick={({target}) => target.classList.toggle('active')}>
....
....
....
</div>

公平

<div onClick={e=> e.target.classList.toggle('active')}>
....
....
....
</div>

或通过声明一个处理单击并执行额外工作的函数

function handleClick(el){
.... Do more stuff
el.classList.toggle('active');


}
<div onClick={({target})=> handleClick(target)}>
....
....
....
</div>
const aDiv = useRef(null);


function app(){
const [isDark, setIsDark] = useState();
useEffect(()=>{
if(isDark){
aDiv.current.classList.add('dark-mode')
}else{
aDiv.current.classList.remove('dark-mode')
}


},[isDark]}
return <div className = "app" ref = {aDiv}> </div>

UseRef 标识元素来切换类,然后用 boolean useState 来跟踪切换,在 true 时,我们得到参考的当前 classList,然后添加一个 className,否则我们删除 className。 所有这些都发生在 useEffect 中,我们的 useState 作为依赖数组。

import { useState } from "react";
import "./App.css";


export default function App() {
const [isActive, setIsActive] = useState(false);


const handleClick = (event) => {
// ️ toggle isActive state on click
setIsActive((current) => !current);
};


return (
<div>
<button className={isActive ? "bg-salmon" : ""} onClick={handleClick}>
Click
</button>
</div>
);
}