(ง •̀_•́)ง Ming and Her Code

References

Cover topics

Life Cycle Method and Event Listener

Life Cycle methods allow you to catch components at certain points in time.

//---A list of lifecycle method:
//componentWillMount()
//componentDidMount()
//componentWillReceiveProps()
//shouldComponentUpdate()
//componentWillUpdate()
//componentDidUpdate()
//componentWillUnmount()

//componentWillMount()
class MyComponent extends React.Component {
 constructor(props) {
  super(props);
 }
 componentWillMount() {
  console.log("Am I in the console?");
 }
 render() {
  return <div />;
 }
}

//componentDidMount()
class MyComponent extends React.Component {
 constructor(props) {
  super(props);
  this.state = {
   activeUsers: null
  };
 }
 componentDidMount() {
  setTimeout(() => {
   //mock API call
   this.setState({
    activeUsers: 1273
   });
  }, 1000);
 }
 render() {
  return (
   <div>
    <h1>Active Users: {this.state.activeUsers}</h1>
   </div>
  );
 }
}

//add event listener: componentDidMount(), componentWillUnmount()
class MyComponent extends React.Component {
 constructor(props) {
  super(props);
  this.state = {
   message: ""
  };
  this.handleEnter = this.handleEnter.bind(this);
  this.handleKeyPress = this.handleKeyPress.bind(this);
 }
 componentDidMount() {
  document.addEventListener("keydown", this.handleKeyPress);
 }
 componentWillUnmount() {
  document.removeEventListener("keydown", this.handleKeyPress);
 }
 handleEnter() {
  this.setState({
   message: this.state.message + "You pressed the enter key! "
  });
 }
 handleKeyPress(event) {
  if (event.keyCode === 13) {
   this.handleEnter();
  }
 }
 render() {
  return (
   <div>
    <h1>{this.state.message}</h1>
   </div>
  );
 }
}

//componentWillUpdate(), componentWillReceiveProps,  componentDidUpdate()
class Dialog extends React.Component {
 constructor(props) {
  super(props);
 }
 componentWillUpdate() {
  console.log("Component is about to update...");
 }
 componentWillReceiveProps(nextProps) {
  console.log(this.props);
  console.log(nextProps);
 }
 componentDidUpdate() {
  console.log("Component has updated...");
 }
 render() {
  return <h1>{this.props.message}</h1>;
 }
}

class Controller extends React.Component {
 constructor(props) {
  super(props);
  this.state = {
   message: "First Message"
  };
  this.changeMessage = this.changeMessage.bind(this);
 }
 changeMessage() {
  this.setState({
   message: "Second Message"
  });
 }
 render() {
  return (
   <div>
    <button onClick={this.changeMessage}>Update</button>
    <Dialog message={this.state.message} />
   </div>
  );
 }
}

//shouldComponentUpdate(), componentWillReceiveProps(), componentDidUpdate()
class OnlyEvens extends React.Component {
 constructor(props) {
  super(props);
 }
 shouldComponentUpdate(nextProps, nextState) {
  console.log("Should I update?");
  if (nextProps.value % 2 == 0) return <h1>{this.props.value}</h1>;
 }
 componentWillReceiveProps(nextProps) {
  console.log("Receiving new props...");
 }
 componentDidUpdate() {
  console.log("Component re-rendered.");
 }
 render() {
  return <h1>{this.props.value}</h1>;
 }
}

class Controller extends React.Component {
 constructor(props) {
  super(props);
  this.state = {
   value: 0
  };
  this.addValue = this.addValue.bind(this);
 }
 addValue() {
  this.setState({
   value: this.state.value + 1
  });
 }
 render() {
  return (
   <div>
    <button onClick={this.addValue}>Add</button>
    <OnlyEvens value={this.state.value} />
   </div>
  );
 }
}

Style, JS and Other

//---inline style, \ is used to escape ruby code
<div style=\{\{ color: "yellow", fontSize: 16 \}\}>Mellow Yellow</div>;
//All property value length units (like height, width, and fontSize) are assumed to be in px unless otherwise specified{fontSize: "4em"}

const styles = {
 color: "purple",
 fontSize: 40,
 border: "2px solid purple"
};
class Colorful extends React.Component {
 render() {
  return <div style={styles}>Style Me!</div>;
 }
}

//---advanced JS
const inputStyle = {
 width: 235,
 margin: 5
};

class MagicEightBall extends React.Component {
 constructor(props) {
  super(props);
  this.state = {
   userInput: "",
   randomIndex: ""
  };
  this.ask = this.ask.bind(this);
  this.handleChange = this.handleChange.bind(this);
 }
 ask() {
  if (this.state.userInput) {
   this.setState({
    randomIndex: Math.floor(Math.random() * 20),
    userInput: ""
   });
  }
 }
 handleChange(event) {
  this.setState({
   userInput: event.target.value
  });
 }
 render() {
  const possibleAnswers = [
   "It is certain",
   "It is decidedly so",
   "Without a doubt",
   "Yes, definitely",
   "You may rely on it",
   "As I see it, yes",
   "Outlook good",
   "Yes",
   "Signs point to yes",
   "Reply hazy try again",
   "Ask again later",
   "Better not tell you now",
   "Cannot predict now",
   "Concentrate and ask again",
   "Don't count on it",
   "My reply is no",
   "My sources say no",
   "Most likely",
   "Outlook not so good",
   "Very doubtful"
  ];
  const answer = possibleAnswers[this.state.randomIndex];
  return (
   <div>
    <input type="text" value={this.state.userInput} onChange={this.handleChange} style={inputStyle} />
    <br />
    <button onClick={this.ask}>Ask the Magic Eight Ball!</button>
    <br />
    <h3>Answer:</h3>
    <p>{answer}</p>
   </div>
  );
 }
}

//---render if/else statement
class MyComponent extends React.Component {
 constructor(props) {
  super(props);
  this.state = {
   display: true
  };
  this.toggleDisplay = this.toggleDisplay.bind(this);
 }
 toggleDisplay() {
  this.setState({
   display: !this.state.display
  });
 }
 render() {
  if (this.state.display) {
   return (
    <div>
     <button onClick={this.toggleDisplay}>Toggle Display</button>
     <h1>Displayed!</h1>
    </div>
   );
  } else {
   return (
    <div>
     <button onClick={this.toggleDisplay}>Toggle Display</button>
    </div>
   );
  }
 }
}

//---Use && for a More Concise Conditional
class MyComponent extends React.Component {
 constructor(props) {
  super(props);
  this.state = {
   display: true
  };
  this.toggleDisplay = this.toggleDisplay.bind(this);
 }
 toggleDisplay() {
  this.setState({
   display: !this.state.display
  });
 }
 render() {
  return (
   <div>
    <button onClick={this.toggleDisplay}>Toggle Display</button>
    {this.state.display && <h1>Displayed!</h1>}
    {/*can use ternary operator*/}
   </div>
  );
 }
}

//---inline style and condition
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"
  };
  if (this.state.input.length > 15) {
   inputStyle.border = "3px solid red";
  }
  return (
   <div>
    <h3>Don't Type Too Much:</h3>
    <input type="text" style={inputStyle} value={this.state.input} onChange={this.handleChange} />
   </div>
  );
 }
}

//---Use Array.map() to Dynamically Render Elements
const textAreaStyles = {
 width: 235,
 margin: 5
};

class MyToDoList extends React.Component {
 constructor(props) {
  super(props);
  this.state = {
   userInput: "",
   toDoList: []
  };
  this.handleSubmit = this.handleSubmit.bind(this);
  this.handleChange = this.handleChange.bind(this);
 }
 handleSubmit() {
  const itemsArray = this.state.userInput.split(",");
  this.setState({
   toDoList: itemsArray
  });
 }
 handleChange(e) {
  this.setState({
   userInput: e.target.value
  });
 }
 render() {
  const items = this.state.toDoList.map(x => <li>{x}</li>);
  return (
   <div>
    <textarea onChange={this.handleChange} value={this.state.userInput} style={textAreaStyles} placeholder="Separate Items With Commas" />
    <br />
    <button onClick={this.handleSubmit}>Create List</button>
    <h1>My "To Do" List:</h1>
    <ul>{items}</ul>
   </div>
  );
 }
}

//Give Sibling Elements a Unique Key Attribute
const frontEndFrameworks = ["React", "Angular", "Ember", "Knockout", "Backbone", "Vue"];

function Frameworks() {
 const renderFrameworks = frontEndFrameworks.map(x => <li key={x + 1}>{x}</li>);
 return (
  <div>
   <h1>Popular Front End JavaScript Frameworks</h1>
   <ul>{renderFrameworks}</ul>
  </div>
 );
}

//---Use Array.filter() to Dynamically Filter an Array
class MyComponent extends React.Component {
 constructor(props) {
  super(props);
  this.state = {
   users: [
    {
     username: "Jeff",
     online: true
    },
    {
     username: "Alan",
     online: false
    },
    {
     username: "Mary",
     online: true
    },
    {
     username: "Jim",
     online: false
    },
    {
     username: "Sara",
     online: true
    },
    {
     username: "Laura",
     online: true
    }
   ]
  };
 }
 render() {
  const usersOnline = this.state.users.filter(user => user.online == true);
  const renderOnline = usersOnline.map(x => <li key={x.username + 1}>{x.username}</li>);
  return (
   <div>
    <h1>Current Online Users:</h1>
    <ul>{renderOnline}</ul>
   </div>
  );
 }
}

//---Render React on the Server with renderToString
//2 key reasons why rendering on the server may be used in a real world app
//1. If you render the initial HTML markup on the server and send this to the client, the initial page load contains all of the page's markup which can be crawled by search engines. (instead of having a relatively empty HTML file and a large bundle of JavaScript on your React apps)
//2. This creates a faster initial page load experience because the rendered HTML is smaller than the JavaScript code of the entire app. React will still be able to recognize your app and manage it after the initial load.
class App extends React.Component {
 constructor(props) {
  super(props);
 }
 render() {
  return <div />;
 }
}

ReactDOMServer.renderToString(<App />);