React

by Abdul Ahmad

HTML

<div id="app"></div>

CSS

body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
}

li {
  margin: 8px 0;
}

h2 {
  font-weight: bold;
  margin-bottom: 15px;
}

.done {
  color: rgba(0, 0, 0, 0.3);
  text-decoration: line-through;
}

input {
  margin-right: 5px;
}

React

const store = {
	inited: false,
  listeners: {},
  listenerNum: 0,
  data: {
  	count: 1,
  },
};

function useState() {
	const [state, setState] = React.useState(store.data);
  let num;
  
  React.useEffect(() => {
    store.listenerNum += 1;
    num = store.listenerNum;
    
		store.listeners[num] = {
    	num,
      setState,
    };
    
    () => delete store.listeners[num];
  }, []);
  
  function incrementCount() {
  	const newState = {
    	...state,
      count: state.count + 1,
    };
  	update({ newState });
  }
  
  function setStateInternal({ data } = {}) {
    const newState = {
      ...state,
      ...data,
    };
    update({ newState });
  }
  
  function update({ newState } = {}) {
  	store.data = newState;
    Object.values(store.listeners).forEach(i => i.setState(newState));
  }

	return {
  	incrementCount,
  	data: state,
    setState: setStateInternal,
  };
}



function App() {
  const { incrementCount, data, setState } = useState();
  const [inputVal, setInputVal] = React.useState('');
	return (
  	<div>
      <button onClick={incrementCount}>
        updateState
      </button>
      <div>
        <input 
          value={inputVal}
          onChange={e => setInputVal(+e.target.value)} 
        />
        <button onClick={() => {
        	setState({ data: { count: inputVal }});
          setInputVal('');
        }}>
          set count
        </button>
      </div>
      <div>
        app: { data.count }
      </div>
      <One />
      <Two />
  	</div>
  );
}

function Two() {
	const { data } = useState();
  
  return (
  	<div>
  	  two: { data.count }
  	</div>
  );
}

function One() {
	const { data } = useState();
  
  return (
  	<div>
  	  one: { data.count }
  	</div>
  );
}

ReactDOM.render(<App />, document.querySelector("#app"));