react 项目实战(五)渲染用户列表
现在我们需要一个页面来展现数据库中记录的用户。
在/src/pages
下新建UserList.js
文件。
创建并导出UserList组件:
import React from 'react'; class UserList extends React.Component { render () { return ( ... ); } } export default UserList;
当页面加载的时候需要调用接口来获取用户列表,并把获取到的用户列表数据存放到组件的state中(this.state.userList):
class UserList extends React.Component { constructor (props) { super(props); this.state = { userList: [] }; } componentWillMount () { fetch('http://localhost:8000/user') .then(res => res.json()) .then(res => { this.setState({ userList: res }); }); } render () { ... } }
在render
方法中,使用数组的map
方法将用户数据渲染为一个表格:
src / pages / UserList.js
import React from 'react'; // 用户列表 class UserList extends React.Component { // 构造器 constructor(props) { super(props); // 定义初始化状态 this.state = { userList: [] }; } /** * 生命周期 * componentWillMount * 组件初始化时只调用,以后组件更新不调用,整个生命周期只调用一次 */ componentWillMount(){ // 请求数据 fetch('http://localhost:8000/user') .then(res => res.json()) .then(res => { /** * 成功的回调 * 数据赋值 */ this.setState({ userList: res }); }); } render() { // 定义变量 const { userList } = this.state; return ( <div> <header> <h1>用户列表</h1> </header> <main> <table> <thead> <tr> <th>用户ID</th> <th>用户名</th> <th>性别</th> <th>年龄</th> </tr> </thead> <tbody> { userList.map((user) => { return ( <tr key={user.id}> <td>{user.id}</td> <td>{user.name}</td> <td>{user.gender}</td> <td>{user.age}</td> </tr> ); }) } </tbody> </table> </main> </div> ); } } export default UserList;
在/src/index.js
文件中添加指向这个页面的路由,并在/src/pages/Home.js
中加入相应的链接:
src / index.js
// 配置路由 import React from 'react'; import ReactDOM from 'react-dom'; // 引入react-router import { Router, Route, hashHistory } from 'react-router'; import HomePage from './pages/Home'; import UserAddPage from './pages/UserAdd'; // 添加用户页 import UserListPage from './pages/UserList' // 用户列表页 // 渲染 ReactDOM.render(( <Router history={hashHistory}> <Route path="/" component={HomePage} /> <Route path="/user/add" component={UserAddPage} /> <Route path="/user/list" component={UserListPage} /> </Router> ), document.getElementById('root'));
src / pages / Home.js
import React from 'react'; import { Link } from 'react-router'; class Home extends React.Component { // 构造器 constructor(props) { super(props); // 定义初始化状态 this.state = {}; } render() { return ( <div> <header> <h1>Welcome</h1> </header> <main> <Link to="/user/list">用户列表</Link> <br /> <Link to="/user/add">添加用户</Link> </main> </div> ); } } export default Home;
最后,我们可以在添加用户之后,使用this.context.router.push
方法来跳转到用户列表页面:
npm i react-prop-types -S
src / pages / UserAdd.js
// 引入 prop-types import PropTypes from 'prop-types'; class UserAdd extends React.Component { handleSubmit (e) { ... fetch('http://localhost:8000/user', { ... }) .then((res) => res.json()) .then((res) => { if (res.id) { alert('添加用户成功'); this.context.router.push('/user/list'); // 跳转到用户列表页面 return; } else { alert('添加失败'); } }) .catch((err) => console.error(err)); } render () { ... } } // 必须给UserAdd定义一个包含router属性的contextTypes // 使得组件中可以通过this.context.router来使用React Router提供的方法 UserAdd.contextTypes = { router: PropTypes.object.isRequired };
完整代码 UserAdd.js:
import React from 'react'; import FormItem from '../components/FormItem'; // 高阶组件 formProvider表单验证 import formProvider from '../utils/formProvider'; // 引入 prop-types import PropTypes from 'prop-types'; // 添加用户组件 class UserAdd extends React.Component { // 按钮提交事件 handleSubmit(e){ // 阻止表单submit事件自动跳转页面的动作 e.preventDefault(); // 定义常量 const { form: { name, age, gender }, formValid} = this.props; // 组件传值 // 验证 if(!formValid){ alert('请填写正确的信息后重试'); return; } // 发送请求 fetch('http://localhost:8000/user', { method: 'post', // 使用fetch提交的json数据需要使用JSON.stringify转换为字符串 body: JSON.stringify({ name: name.value, age: age.value, gender: gender.value }), headers: { 'Content-Type': 'application/json' } }) // 强制回调的数据格式为json .then((res) => res.json()) // 成功的回调 .then((res) => { // 当添加成功时,返回的json对象中应包含一个有效的id字段 // 所以可以使用res.id来判断添加是否成功 if(res.id){ alert('添加用户成功!'); this.context.router.push('/user/list'); // 跳转到用户列表页面 return; }else{ alert('添加用户失败!'); } }) // 失败的回调 .catch((err) => console.error(err)); } render() { // 定义常量 const {form: {name, age, gender}, onFormChange} = this.props; return ( <div> <header> <div>添加用户</div> </header> <main> <form onSubmit={(e) => this.handleSubmit(e)}> <FormItem label="用户名:" valid={name.valid} error={name.error}> <input type="text" value={name.value} onChange={(e) => onFormChange('name', e.target.value)}/> </FormItem> <FormItem label="年龄:" valid={age.valid} error={age.error}> <input type="number" value={age.value || ''} onChange={(e) => onFormChange('age', e.target.value)}/> </FormItem> <FormItem label="性别:" valid={gender.valid} error={gender.error}> <select value={gender.value} onChange={(e) => onFormChange('gender', e.target.value)}> <option value="">请选择</option> <option value="male">男</option> <option value="female">女</option> </select> </FormItem> <br /> <input type="submit" value="提交" /> </form> </main> </div> ); } } // 必须给UserAdd定义一个包含router属性的contextTypes // 使得组件中可以通过this.context.router来使用React Router提供的方法 UserAdd.contextTypes = { router: PropTypes.object.isRequired }; // 实例化 UserAdd = formProvider({ // field 对象 // 姓名 name: { defaultValue: '', rules: [ { pattern: function (value) { return value.length > 0; }, error: '请输入用户名' }, { pattern: /^.{1,4}$/, error: '用户名最多4个字符' } ] }, // 年龄 age: { defaultValue: 0, rules: [ { pattern: function(value){ return value >= 1 && value <= 100; }, error: '请输入1~100的年龄' } ] }, // 性别 gender: { defaultValue: '', rules: [ { pattern: function(value) { return !!value; }, error: '请选择性别' } ] } })(UserAdd); export default UserAdd;
这样我们在添加用户之后就可以立即在列表中看到最新添加的用户了: