Artigo original: React - Change Inline CSS Conditionally Based on Component State

Se você estiver com problemas com o desafio Mudar CSS em linha condicionalmente com base no estado do componente do freeCodeCamp, provavelmente, não está sozinho.

Nesse desafio, você precisa adicionar código para alterar de modo condicional o CSS em linha com base no estado, ou state, de um componente do React.

Ao chegar ao desafio, este é o código que você verá:

class GateKeeper extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      input: ''
    };
    this.handleChange = this.handleChange.bind(this);
  }
  handleChange(event) {
    this.setState({ input: event.target.value })
  }
  render() {
    let inputStyle = {
      border: '1px solid black'
    };
    // Altere o código abaixo desta linha

    // Altere o código acima desta linha
    return (
      <div>
        <h3>Don't Type Too Much:</h3>
        <input
          type="text"
          style={inputStyle}
          value={this.state.input}
          onChange={this.handleChange} />
      </div>
    );
  }
};

Perceba que um objeto de estilo em linha, chamado inputStyle, já foi declarado com estilização padrão.

Seu objetivo nesse desafio é atualizar inputStyle de maneira que a borda do elemento input seja 3px solid red quando houver mais de 15 caracteres na entrada. Observe que o texto na caixa de entrada é salvo no state do componente como input:

...
this.state = {
  input: ''
};
...

Quase lá, mas ainda não está certo

Imagine que, após ler a descrição e as instruções, você tenha essa ideia:

class GateKeeper extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      input: ''
    };
    this.handleChange = this.handleChange.bind(this);
  }
  handleChange(event) {
    this.setState({ input: event.target.value })
  }
  render() {
    let inputStyle = {
      border: '1px solid black'
    };
    // Altere o código abaixo desta linha
    const char = 15;
    if(this.state.input > char) {
      inputStyle = {
        border:'3px solid red'
      }
    }  
    // Altere o código acima desta linha
    return (
      <div>
        <h3>Don't Type Too Much:</h3>
        <input
          type="text"
          style={inputStyle}
          value={this.state.input}
          onChange={this.handleChange} />
      </div>
    );
  }
};

Ao tentar enviar, porém, o código não passa em todos os testes. Vamos examinar mais de perto o que está havendo.

Soluções

Usando uma instrução if

Declarar char é uma boa ideia, mas examine a condição no bloco if:

if(this.state.input > char) {
  inputStyle = {
    border:'3px solid red'
  }
}  

Lembre-se de que this.state.input é o valor da caixa de entrada e que é uma string. Por exemplo, ela pode ser "testando testando 1, 2, 3".

Se você inserir "testando testando 1, 2, 3" na caixa de texto e se registrar this.state.input no console (usando console.log):

class GateKeeper extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      input: ''
    };
    this.handleChange = this.handleChange.bind(this);
  }
  handleChange(event) {
    this.setState({ input: event.target.value })
  }
  render() {
    let inputStyle = {
      border: '1px solid black'
    };
    // Altere o código abaixo desta linha
    const char = 15;
    console.log(this.state.input);
    if(this.state.input > char) {
      inputStyle = {
        border:'3px solid red'
      }
    }  
    // Altere o código acima desta linha
    return (
      <div>
        <h3>Don't Type Too Much:</h3>
        <input
          type="text"
          style={inputStyle}
          value={this.state.input}
          onChange={this.handleChange} />
      </div>
    );
  }
};

Você verá testando testando 1, 2, 3 no console.

Além disso, se você registrar this.state.input > char no console, verá que seu valor é false:

class GateKeeper extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      input: ''
    };
    this.handleChange = this.handleChange.bind(this);
  }
  handleChange(event) {
    this.setState({ input: event.target.value })
  }
  render() {
    let inputStyle = {
      border: '1px solid black'
    };
    // Altere o código abaixo desta linha
    const char = 15;
    console.log(this.state.input > char);
    if(this.state.input > char) {
      inputStyle = {
        border:'3px solid red'
      }
    }  
    // Altere o código acima desta linha
    return (
      <div>
        <h3>Don't Type Too Much:</h3>
        <input
          type="text"
          style={inputStyle}
          value={this.state.input}
          onChange={this.handleChange} />
      </div>
    );
  }
};

Dito de maneira simplificada, não é possível comparar uma string (this.state.input) diretamente com char, que é um número.

Em vez disso, chame .length em this.state.input para obter o tamanho da string e compare-o a count:

class GateKeeper extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      input: ''
    };
    this.handleChange = this.handleChange.bind(this);
  }
  handleChange(event) {
    this.setState({ input: event.target.value })
  }
  render() {
    let inputStyle = {
      border: '1px solid black'
    };
    // Altere o código abaixo desta linha
    const char = 15;
    if(this.state.input.length > char) {
      inputStyle = {
        border:'3px solid red'
      }
    }  
    // Altere o código acima desta linha
    return (
      <div>
        <h3>Don't Type Too Much:</h3>
        <input
          type="text"
          style={inputStyle}
          value={this.state.input}
          onChange={this.handleChange} />
      </div>
    );
  }
};

Como o tamanho da string "testando testando 1, 2, 3" é de 23 caracteres (incluindo espaços e vírgulas), a borda da caixa de entrada deverá ser vermelha:

Usando um operador ternário

Um operador ternário ou condicional é como uma instrução if...else de apenas uma linha, o que pode ajudar você a reduzir significativamente o tamanho do seu código.

Volte agora à sua solução e remova tudo, exceto a variável char:

class GateKeeper extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      input: ''
    };
    this.handleChange = this.handleChange.bind(this);
  }
  handleChange(event) {
    this.setState({ input: event.target.value })
  }
  render() {
    let inputStyle = {
      border: '1px solid black'
    };
    // Altere o código abaixo desta linha

    // Altere o código acima desta linha
    return (
      <div>
        <h3>Don't Type Too Much:</h3>
        <input
          type="text"
          style={inputStyle}
          value={this.state.input}
          onChange={this.handleChange} />
      </div>
    );
  }
};

Agora, pegue a condição que você usou na sua instrução if de antes e use-a na primeira parte do operador ternário: this.state.input.length > char ?  :  ;

Tudo o que estiver entre ? e : indica o que ocorrerá se a instrução retornar true. Você pode simplesmente copiar o código que estava dentro da instrução if de antes: this.state.input.length > char ? inputStyle = { border:'3px solid red' } :  ;

Depois disso, você precisa lidar com a parte do else do operador ternário, que é tudo o que se encontra entre : e ;.

Embora você não tenha usado uma instrução else na sua primeira solução, você conseguiu usar inputStyle como estava de modo eficaz. Assim, basta usar inputStyle do modo como foi declarado anteriormente no código: this.state.input.length > char ? inputStyle = { border:'3px solid red' } : inputStyle;

Sua solução completa deverá ter esta aparência:

class GateKeeper extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      input: ''
    };
    this.handleChange = this.handleChange.bind(this);
  }
  handleChange(event) {
    this.setState({ input: event.target.value })
  }
  render() {
    let inputStyle = {
      border: '1px solid black'
    };
    // Altere o código abaixo desta linha
    const char = 15;
    this.state.input.length > char ? inputStyle = { border:'3px solid red' } : inputStyle;
    // Altere o código acima desta linha
    return (
      <div>
        <h3>Don't Type Too Much:</h3>
        <input
          type="text"
          style={inputStyle}
          value={this.state.input}
          onChange={this.handleChange} />
      </div>
    );
  }
};

Está resolvido – agora, você deve ser capaz de passar no desafio! Agora, você já sabe como estilizar de modo condicional os componentes do React da maneira que quiser.