How to conditionally add attributes to react DOM element

江枫思渺然 提交于 2019-12-22 06:59:07

问题


I have a scenario where I'm using React.js to create a div using the following code :

React.createElement('div', {}, "div content") 

Some additional javascript processing will allow me afterwards to deduce if this div needs to have the className attribute set to" ClassA" or "ClassB" or if it shouldn't have className at all.

Is there a way in javascript to access the div that was created from the React DOM and to add to it the className attribute?

Note : I couldn't achieve this is JSX so I resorted to the createElement method.

Edit: it is worth to mention that i might need to conditionally add attributes other than className. For example, I might need to add to an anchor tag an "alt" attribute or not based on conditional logic. Thank you in advance.


回答1:


Use JSX spread. Build and object with props, modify it however you like and pass it to component like so:

const props = {
    name: 'SomeName'
}

if (true) {
    props.otherName = 'otherName';
}

return (
    <SomeComponent {...props}/>
);

See that ... syntax? That spread operator do the job - all props will end up as separate attributes on your component.

Take a look at this plunk: http://www.webpackbin.com/4JzKuJ9C-




回答2:


Since you were trying to initially have your logic in JSX. I have a jsx solution that uses state

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      classValue: ''
    }
  }
  handleClick = () => {
    if(this.state.classValue == '') {
      this.setState({classValue : 'green'});
    }
    else if(this.state.classValue == 'green') {
      this.setState({classValue : 'blue'});
    }
    else {
       this.setState({classValue : 'green'});
    }
  }
  render() {
    return (
    <div>
      <div className={this.state.classValue}>Hello World</div>
      <button onClick={this.handleClick()}>Toggle</button>
    </div>
  )}
}

ReactDOM.render(<App/>, document.getElementById('app'));
.green {
  background-color: green;
}
.blue {
  background-color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react-dom.min.js"></script>
<div id="app"></div>

The example shows how can you change your className similarly using state you can set whatever attributes you like to change.




回答3:


You can use ES6 syntax to achieve the desired functionality

const yourComponentProps = {
  [ifThisIsTrue ? 'useThisName' : 'useAnotherName']: 'yourDesiredValue',
};

return <YourComponent {...yourComponentProps} />



回答4:


This is a quite normal situation in React and requires virtually no special handling.

Note: It is best to hand props down the component tree declaratively but if that is not an option you can bind listener functions in componentDidMount and unbind them in componentWillUnmount as shown in the following example. So long as they call setState, your component's render function will get triggered.

const { Component, cloneElement } = React

class Container extends Component {
  constructor(props) {
    super(props)
    this.state = { classNames: [ 'foo' ] }
    this.appendClassName = () => {
      const { classNames } = this.state
      this.setState({ classNames: [ ...classNames, `foo_${classNames.length}` ] })
    }
  }
  componentDidMount() {
    document.querySelector('button').addEventListener('click', this.appendClassName)
  }
  componentWillUnmount() {
    document.querySelector('button').removeEventListener('click', this.appendClassName)
  }
  render() {
    const { children } = this.props
    const { classNames } = this.state
    
    return <div className={classNames.join(' ')}>{children}</div>
  }
}


ReactDOM.render(<Container>I am content</Container>, document.getElementById('root'))
.foo {
  font-family: monospace;
  border: 1px solid rgb(100, 50, 50);
  font-size: 1rem;
  border-style: solid;
  border-width: 1px;
  width: 50vw;
  height: 50vh;
  margin: auto;
  display: flex;
  align-self: center;
  justify-content: center;
  align-items: center;
}

.foo.foo_1 {
  font-size: 1.5rem;
  background-color: rgb(200, 100, 200);
}

.foo.foo_2 {
  font-size: 2rem;
  border-radius: 3px 7px;
  background-color: rgb(180, 120, 200);
}

.foo.foo_3 {
  border-style: dashed;
  background-color: rgb(175, 130, 180);
}

.foo.foo_4 {
  border-width: 2px;
  background-color: rgb(160, 165, 170);
}

.foo.foo_5 {
  border-width: 1rem;
  background-color: rgb(150, 200, 150);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<button>Click me</button>
<div id="root"></div>

P.S. - Avoid using componentWillMount, it can lead to bugs in the lifecycle and there is talk that it may be removed in a future version of React. Always make async side-effect laden requests within componentDidMount and clean them up in componentWillUnmount. Even if you have nothing to render, you are best off rendering a placeholder component until your data arrives (best option for fast loading), or nothing at all.



来源:https://stackoverflow.com/questions/40035230/how-to-conditionally-add-attributes-to-react-dom-element

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!