简体   繁体   English

有没有更简洁的方法来编写这个 React 代码?

[英]Is there a cleaner way to write this React code?

First time using react.第一次使用反应。 Writing a piece of code where I want the element I click on to be highlighted, while the unselected elements get unhighlighted.编写一段代码,我希望我单击的元素突出显示,而未选择的元素则不突出显示。 Basically, I want the state to change to true based on the element I click, and the other states to be toggled to false.基本上,我希望根据我单击的元素将状态更改为 true,并将其他状态切换为 false。

My question is, is there a more elegant to write this code?我的问题是,有没有更优雅的方式来编写这段代码? I originally tried to base it on event.target but I don't know how to bind a state to a specific element.我最初尝试基于event.target但我不知道如何将状态绑定到特定元素。 While below does work for my purposes, I do wonder if there's a way to more dynamically use setState without having to write separate methods for each case...虽然下面确实适合我的目的,但我想知道是否有一种方法可以更动态地使用 setState 而不必为每种情况编写单独的方法......


export default class CharacterNav extends Component {
    constructor(props) {
        super(props);
        this.state = {
            profileHighlighted: true,
            recruitHighlighted: false,
            artsHighlighted: false,
            talentsHighlighted: false,
            affectionHighlighted: false,
        }

        this.changeProfileHighlight = this.changeProfileHighlight.bind(this);
        this.changeRecruitHighlight = this.changeRecruitHighlight.bind(this);
        this.changeArtsHighlight = this.changeArtsHighlight.bind(this);
        this.changeTalentsHighlight = this.changeTalentsHighlight.bind(this);
        this.changeAffectionHighlight = this.changeAffectionHighlight.bind(this);
        this.resetNavState = this.resetNavState.bind(this);
    }

    changeProfileHighlight () {
        this.setState({
            profileHighlighted: true,
            recruitHighlighted: false,
            artsHighlighted: false,
            talentsHighlighted: false,
            affectionHighlighted: false
        });
    }
    changeRecruitHighlight () {
        this.setState({
            profileHighlighted: false,
            recruitHighlighted: true,
            artsHighlighted: false,
            talentsHighlighted: false,
            affectionHighlighted: false
        });
    }
    changeArtsHighlight () {
        this.setState({
            profileHighlighted: false,
            recruitHighlighted: false,
            artsHighlighted: true,
            talentsHighlighted: false,
            affectionHighlighted: false
        });
    }
    changeTalentsHighlight () {
        this.setState({
            profileHighlighted: false,
            recruitHighlighted: false,
            artsHighlighted: false,
            talentsHighlighted: true,
            affectionHighlighted: false
        });
    }
    changeAffectionHighlight () {
        this.setState({
            profileHighlighted: false,
            recruitHighlighted: false,
            artsHighlighted: false,
            talentsHighlighted: false,
            affectionHighlighted: true
        });
    }


    render () {
        let divClass = this.props.characterSelected ?
                "blueBackground" :"hideElement"; 
        let profilehighlightclass = this.state.profileHighlighted ? 'highlighted' : 'unhighlighted';
        let recruithighlightclass = this.state.recruitHighlighted ? 'highlighted' : 'unhighlighted';
        let artshighlightclass = this.state.artsHighlighted ? 'highlighted' : 'unhighlighted';
        let talentshighlightclass = this.state.talentsHighlighted ? 'highlighted' : 'unhighlighted';
        let affectionhighlightclass = this.state.affectionHighlighted ? 'highlighted' : 'unhighlighted';

        return(
            <div>
                <ul className={divClass}>
                    <li><h3 onClick={this.changeProfileHighlight} name='profileHighlighted' className={profilehighlightclass}>Profile</h3></li>
                    <li><h3 onClick={this.changeRecruitHighlight} name='recruitHighlighted' className={recruithighlightclass}>Recruitment</h3></li>
                    <li><h3 onClick={this.changeArtsHighlight} name='artsHighlighted' className={artshighlightclass}>Arts</h3></li>
                    <li><h3 onClick={this.changeTalentsHighlight} name='talentsHighlighted' className={talentshighlightclass}>Talents</h3></li>
                    <li><h3 onClick={this.changeAffectionHighlight} name='affectionHighlighted' className={affectionhighlightclass}>Affection</h3></li>
                </ul>
            </div>
        )
    }
}

Yes, you can hold in your state the name of the highlighted element.是的,您可以在您的状态中保留突出显示元素的名称。

something like :就像是 :

 export default class CharacterNav extends Component { constructor(props) { super(props); this.state = { highlighted: "profile", }; } setHighlighted = e => { this.setState({ highlighted: e.target.name, }); }; toggleHighlight = selectedTab => { return this.state.highlighted === selectedTab ? "highlighted" : "unhighlighted"; }; render() { let divClass = this.props.characterSelected ? "blueBackground" : "hideElement"; return ( <ul className={divClass}> <li> <h3 onClick={this.setHighlighted} name="profile" className={this.toggleHighlight("profile")} > Profile </h3> </li> <li> <h3 onClick={this.setHighlighted} name="recruit" className={this.toggleHighlight("recruit")} > Recruitment </h3> </li> <li> <h3 onClick={this.setHighlighted} name="arts" className={this.toggleHighlight("arts")} > Arts </h3> </li> <li> <h3 onClick={this.setHighlighted} name="talents" className={this.toggleHighlight("talents")} > Talents </h3> </li> <li> <h3 onClick={this.setHighlighted} name="affection" className={this.toggleHighlight("affection")} > Affection </h3> </li> </ul> ); } }

You can also improve your li rendering by iterating over an array您还可以通过迭代数组来改进 li 渲染

 export default class CharacterNav extends Component { constructor(props) { super(props); this.state = { highlighted: 'profile' } this.setHighlighted = this.setHighlighted.bind(this); } setHighlighted(e) { this.setState({ highlighted: e.target.name }); } render () { let divClass = this.props.characterSelected ? "blueBackground" :"hideElement"; return( <div> <ul className={divClass}> ['Profile', 'Recruitment', 'Talents', 'Affection'].map(item => { const name = item.toLowerCase(); return ( <li> <h3 onClick={this.setHighlighted} name={name} className={name === this.state.highlighted ? 'highlighted' : 'unhighlighted'}> {item} </h3> </li> ) }) </ul> </div> ) } }

Optimized way优化方式

class App extends React.Component {
  state = {
    arr: [
      { id: 1, name: "profileHighlighted", title: "Profile" },
      { id: 2, name: "recruitHighlighted", title: "Recruitment" },
      { id: 3, name: "changeArtsHighlight", title: "Arts" },
      { id: 4, name: "talentsHighlighted", title: "Talents" },
      { id: 5, name: "affectionHighlighted", title: "Affection" }
    ],
    heightlighted:''
  };
  changeProfileHighlight = id => {
     this.setState({heightlighted:id})
  };

  render() {
    return (
      <div>
        <ul>
          {this.state.arr.map(({ name, id, title }) => (
            <li>
              <h3
                onClick={() => this.changeProfileHighlight(id)}
                name={name}
                className={"profilehighlightclass"}
              >
                <span style={{color:this.state.heightlighted===id?'red':''}}>{title}</span>
              </h3>
            </li>
          ))}
        </ul>
      </div>
    );
  }
}

Just add and remove class name :只需添加和删除类名:

import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";


function App() {

  const highlightMe=(e)=>{    
    var els = document.getElementsByClassName("highlight");
    for(var i = 0; i < els.length; i++){   
      els.item(i).classList.remove("highlight");
    }
    e.target.classList.add("highlight");
  }


  return (
    <div className="App">
      <div>
                <ul className={''}>
                    <li><h3 onClick={highlightMe} name='profileHighlighted' className={"profileHighlighted"}>Profile</h3></li>
                    <li><h3 onClick={highlightMe} name='recruitHighlighted' className={"recruitHighlighted"}>Recruitment</h3></li>
                    <li><h3 onClick={highlightMe} name='artsHighlighted' className={"artsHighlighted"}>Arts</h3></li>
                    <li><h3 onClick={highlightMe} name='talentsHighlighted' className={"talentsHighlighted"}>Talents</h3></li>
                    <li><h3 onClick={highlightMe} name='affectionHighlighted' className={"affectionHighlighted"}>Affection</h3></li>
                </ul>
            </div>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

output : https://codesandbox.io/s/tender-http-pl4xy输出: https : //codesandbox.io/s/tender-http-pl4xy

  toggleHighlight = e => {
    const copy = { ...this.state };
    Object.keys(copy).forEach(key => (copy[key] = false));
    this.setState({ ...copy, [e.target.id]: true }, () => console.log(this.state));
  };

This will toggle the boolean value of your state properties.这将切换状态属性的布尔值。

getClassName = element =>
    this.state[element] ? 'highlighted' : 'unhighlighted';

This will toggle your className .这将切换您的className

To improve accessibility, you should add a keyboard event.为了提高可访问性,您应该添加一个键盘事件。 Albeit it's generally not recommended to have onClick events on non-interactive elements like h3 .尽管通常不建议在h3等非交互式元素上使用onClick事件。

<h3
 onClick={this.toggleHighlight}
 onKeyPress={this.toggleHighlight}
 role="button"
 id="profileHighlighted"
 className={this.getClassName('profileHighlighted')}
>
  Profile
</h3>

And do use map do render your list as recommended in previous answeres并按照以前的答案中的建议使用map渲染您的列表

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM