2017年12月10日 星期日

React with Redux -- todo list

Everyone know todo list is a good practice at front-end programming.
I also create one, and notes some interesting points.
Let's start it.
First, download create-react-app by npm.
$ npm i -g create-react-app
Then use it create a new project `react-todo`
$ create-react-app react-todo
Waiting few seconds. Then you will see a directory call `react-todo` at there.
Ok, `cd src/` then you can find App.js.
We don't deal other things. Focus on todo list. So let's insert some html in App component!
<ul>
  <li>todo 1</li>
  <li>todo 2</li>
  <li>todo 3</li>
</ul>
You can see the result by execute `npm start`.
I usually use two checker. `flow` & `npm test`. `npm test` is provided by create-react-app. It using jest(when I write this).
And `flow` is a type checker. It can check type for you, and best thing is you can choose you want to use it or not, by adding comment at the file's head:
/*
@flow
*/
to open, or close it by no adding these.
Ok, so now we know this part is todo-list. Good, I use component TodoList instead of hard code at here first.
<TodoList />
$ mkdir TodoList/ && cd TodoList/ && touch index.js
Then `import TodoList from './TodoList'` to get component.
It doesn't hard. Next we that TodoList can work.
class TodoList extends Component {
  constructor(props) {
    super(props);
    this.state = {
      todos: [], // string[]
      todoStr: "" // string
    }
  }
  // evt of nextTodo is Input Element's event, listen to OnChange
  nextTodo = (evt) => {
    this.setState({
      todoStr: evt.target.value
    });
  };
  // evt of addTodo is button Element's event, listen to OnClick
  addTodo = (evt) => {
    this.setState({
      todos: [...this.state.todos, this.state.todoStr]
    })
  }
  render = () => (
    <div>
      <input value={this.state.todoStr} onChange={this.nextTodo}/>
      <button onClick={this.addTodo}>Add Todo</button>
      <ul>{
        this.state.todos.map((todo, index) => <li key={index}>{todo}</li>)
      }</ul>
    </div>
  )
}
It works. Then you can trying to spread out Todo Component, if you need a more complex Todo component.
Then we go to see redux.
import { createStore } from "redux";

type TodoAction = {
  type: string,
  index?: number,
  todoStr?: string
};

const todocer = (state: string[] = [], action: TodoAction) => {
  switch (action.type) {
    case "ADD_TODO":
      return [...state, action.todoStr];
    case "DELETE_TODO":
      return state.filter((todo, index) => index !== action.index);
    default:
      return state;
  }
};

export default createStore(todocer);
It's a little bit complex, because I use flow in the example here, but still, you can see we are doing the same things. But we move TodoList's data structure management from TodoList component to our reducer todocer. Why we have to do this? Because I want to talk about redux? I am joking. The truth is if our project grow, and other part depends on todo-list's status to decide what should them do. In traditional way, we will go to a hell about data dependencies, a ref b, b ref c... And finally, infinite task be created, but you almost can not find out the begin of this chaos.
Redux didn't solve the problem, but it that flow of data changing is visible & traceable,
so on we can find out the problem instead of rewrite it! Oh! I forgot everyone rewrite front-end every six months. Good!
Next we use Provider connect react & redux, you can without it! That's true, I usually use import store from 'path/to/store' to manage access, but today let's use react-redux.
import { Provider } from "react-redux";
import store from "path/to/store";

<Provider store={store}>
  <App />
</Provider>
This is how we use react-redux, it will send store by context to every child component.
So you will get the right to access the store you put into Provider by
this.context.store
ps. I don't want to talk about redux's API, you can google it.
I think this trick cause some problem, we have to import a lot of thing when testing, and that is boring. And connect function is too complex to hard to learn how to use. Of course, once you got the point, that will be easy.
Today's article end at here, thanks for read.




Ok

沒有留言:

張貼留言