javascript React Refresher

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了javascript React Refresher相关的知识,希望对你有一定的参考价值。

function Button(props) {
  const handleClick = () => props.onClickFunction(props.increment)
  
  return (
    <button onClick={ handleClick }>
      +{props.increment}
    </button>
    )
}

function Display(props) {
  return (
    <div>{props.message}</div>
  )
}

function App() {
  const [ counter, setCounter ] = useState(0)
  const incrementCounter = ( incrementValue ) => setCounter( counter + incrementValue)
  
    
  return (
    <div>
      <Button onClickFunction={incrementCounter} increment={1} /> 
      <Button onClickFunction={incrementCounter} increment={5} /> 
      <Button onClickFunction={incrementCounter} increment={10} /> 
      <Button onClickFunction={incrementCounter} increment={100} /> 
      <Display message={ counter }/>
    </div>
  )
}


ReactDOM.render(
  <App />,
  document.getElementById('mountNode')
)
const StarsDisplay = props => (
  <>
    {utils.range(1, props.count).map(starId => (
      <div key={starId} className="star" />
    ))}
  </>
)

const PlayNumber = props => (
  <button
    className="number"
    style={{backgroundColor: colors[props.status]}}
    onClick={() => props.onClick(props.number, props.status)}
  >
    {props.number}
  </button>
)

const PlayAgain = props => (
	<div className="game-done">
  	<div 
    	className="message"
      style={{ color: props.gameStatus === 'lost' ? 'red' : 'green'}}
    >
  	  {props.gameStatus === 'lost' ? 'Game Over' : 'Nice'}
  	</div>
	  <button onClick={props.onClick}>Play Again</button>
	</div>
);

// Custom Hook
const useGameState = () => {
  const [stars, setStars] = useState(utils.random(1, 9))
  const [availableNums, setAvailableNums] = useState(utils.range(1, 9))
  const [candidateNums, setCandidateNums] = useState([])
  const [secondsLeft, setSecondsLeft] = useState(10)

	useEffect(() => {
  	if (secondsLeft > 0 && availableNums.length > 0) {
      const timerId = setTimeout(() => {
	      setSecondsLeft(secondsLeft - 1)
      }, 1000)
      // return function to clean up side effect
    	return () => clearTimeout(timerId)
  	}
  })
  
/* --- Manual resetting of state ---
  const resetGame = () => {
  	setStars(utils.random(1, 9));
    setAvailableNums(utils.range(1, 9));
    setCandidateNums([]);
  };
*/
  
  const setGameState = (newCandidateNums) => {
    if (utils.sum(newCandidateNums) !== stars) {
      setCandidateNums(newCandidateNums)
    } else {
      const newAvailableNums = availableNums.filter(
        n => !newCandidateNums.includes(n)
      )
      setStars(utils.randomSumIn(newAvailableNums, 9))
      setAvailableNums(newAvailableNums)
      setCandidateNums([])
    }
  }

  return { stars, availableNums, candidateNums, secondsLeft, setGameState }
}


const Game = (props) => {
  const {
    stars, 
    availableNums,
    candidateNums,
    secondsLeft,
    setGameState,
  } = useGameState()

  const candidatesAreWrong = utils.sum(candidateNums) > stars
  const gameStatus = availableNums.length === 0 
  	? 'won'
    : secondsLeft === 0 ? 'lost' : 'active'  

  const numberStatus = number => {
    if (!availableNums.includes(number)) {
      return 'used'
    }
    if (candidateNums.includes(number)) {
      return candidatesAreWrong ? 'wrong' : 'candidate'
    }
    return 'available'
  }

  const onNumberClick = (number, currentStatus) => {
    if (gameStatus !== 'active' || currentStatus === 'used') {
      return
    }
    
    const newCandidateNums =
      currentStatus === 'available'
        ? candidateNums.concat(number)
        : candidateNums.filter(cn => cn !== number)

    setGameState(newCandidateNums)
  }

  return (
    <div className="game">
      <div className="help">
        Pick 1 or more numbers that sum to the number of stars
      </div>
      <div className="body">
        <div className="left">
          {gameStatus !== 'active' ? (
          	// <PlayAgain onClick={resetGame} gameStatus={gameStatus} /> --- Manual Method ---
            <PlayAgain onClick={props.startNewGame} gameStatus={gameStatus} />
          ) : (
          	<StarsDisplay count={stars} />
          )}
        </div>
        <div className="right">
          {utils.range(1, 9).map(number => (
            <PlayNumber
              key={number}
              status={numberStatus(number)}
              number={number}
              onClick={onNumberClick}
            />
          ))}
        </div>
      </div>
      <div className="timer">Time Remaining: {secondsLeft}</div>
    </div>
  )
}

const StarMatch = () => {
  const [gameId, setGameId] = useState(1)
  return <Game key={gameId} startNewGame={() => setGameId(gameId + 1)}/>
}

// Color Theme
const colors = {
  available: 'lightgray',
  used: 'lightgreen',
  wrong: 'lightcoral',
  candidate: 'deepskyblue',
};

// Math science
const utils = {
  // Sum an array
  sum: arr => arr.reduce((acc, curr) => acc + curr, 0),

  // create an array of numbers between min and max (edges included)
  range: (min, max) => Array.from({length: max - min + 1}, (_, i) => min + i),

  // pick a random number between min and max (edges included)
  random: (min, max) => min + Math.floor(max * Math.random()),

  // Given an array of numbers and a max...
  // Pick a random sum (< max) from the set of all available sums in arr
  randomSumIn: (arr, max) => {
    const sets = [[]];
    const sums = [];
    for (let i = 0; i < arr.length; i++) {
      for (let j = 0, len = sets.length; j < len; j++) {
        const candidateSet = sets[j].concat(arr[i]);
        const candidateSum = utils.sum(candidateSet);
        if (candidateSum <= max) {
          sets.push(candidateSet);
          sums.push(candidateSum);
        }
      }
    }
    return sums[utils.random(0, sums.length)];
  },
};

ReactDOM.render(<StarMatch />, mountNode);	

以上是关于javascript React Refresher的主要内容,如果未能解决你的问题,请参考以下文章

javascript React-router启动码#react

javascript [React snippets]来自Udacity Nanodegree #React

如何在 React / React Native 中使用 Emscripten 编译的 JavaScript

在开始React之前,你需要学好这些JavaScript

如何使 Javascript/React/Typescript 获取调用异步?

Javascript/React:溢出 X 可见,溢出 Y 自动