#14 React.js 加载、刷新数据 - 高阶组件


  • 0
    administrators

    题目 #10 React.js 加载、刷新数据 这种加载数据、刷新数据的行为很常见,现在把这种逻辑抽离到高阶组件当中去。完成高阶组件 loadAndRefresh,它具有以下功能:

    class Post extends Component {
      render () {
        return (
          <div>
            <p>{this.props.content}</p>
            <button onClick={() => this.props.refresh()}>刷新</button>
          </div>
        )
      }
    }
    
    Post = loadAndRefresh('/post')(Post)
    

    高阶组件 loadAndRefresh 接受一个 url 作为参数,然后返回一个接受组件作为参数的函数,这个新函数返回一个新的组件。新的组件渲染的时候会给传入的组件设置 contentrefresh 作为 props

    环境中已经定义好了一个 getData(url) 的返回 Promise 的函数,它会去服务器取一个字符串的文本,你需要通过 contentprops 把它传给被包裹的组件。组件在第一次加载还有 refresh 的时候会去服务器取数据。

    另外,组件在加载数据的时候,content 显示 数据加载中...。而且,所有传给 loadAndRefresh 返回的组件的 props 要原封不动传给被包裹的组件。


  • 1
    administrators

    @francis

    const loadAndRefresh = (url) => (WrappedComponent) => {
      return class extends Component {
        componentWillMount () {
          this._loadData()
        }
        
        async _loadData () {
          this.setState({ content: '数据加载中...' })
          const content = await getData(url)
          this.setState({ content })
        }
      
        render () {
          const props = {
            content: this.state.content,
            refresh: this._loadData.bind(this),
            ...this.props
          }
          return (
            <WrappedComponent {...props} />
          )
        }
      }
    }
    
    

  • 0

    @胡子大哈 (url) => (WrappedComponent) 这样 可以 为啥 (url,PostOld)=>{ return class Post extends Component {不行?


  • 0

    @francis#14 React.js 加载、刷新数据 - 高阶组件 中说:

    (url) => (WrappedComponent) 这样 可以 为啥 (url,PostOld)=>{ return class Post extends Component {不行?


  • 1
    administrators

    @francis

    因为题目要求是这种调用方式:

    class Post extends Component {
      render () {
        return (
          <div>
            <p>{this.props.content}</p>
            <button onClick={() => this.props.refresh()}>刷新</button>
          </div>
        )
      }
    }
    
    Post = loadAndRefresh('/post')(Post)
    

    注意最后一行代码:Post = loadAndRefresh('/post')(Post)

    这种方式其实是 React 里面高阶组件常用的套路,在 React-redux 里面就用到。loadAndRefresh 是一个函数,这个函数接受一个参数,然后返回一个函数,这个函数接受组件作为参数,然后再返回一个组件。


  • 0

    @胡子大哈 奥奥 懂了 就可以做到链式调用那样 了 谢谢哈


  • 0

    @胡子大哈 感觉 你写的代码很简洁 但是 有些地方看起来 不是很容易看懂 像这个 const content = await getData(url)
    this.setState({ content }) 和this.setState({ content:content }) 这些 写法 是不是得去 再看看基础那部分


  • 0
    administrators

    @francis 嗯嗯,这些还是比较常用的语法,掌握了这些语法看起来就比较容易了。


  • 0

    @胡子大哈 return class extends Component { ... } class 关键字后面可以直接忽略函数名?


  • 0
    administrators

    @Saku 可以的,匿名类


  • 0

    @胡子大哈 额 不好意思哈 this.setState({ content }) 和this.setState({ content:content }) 这个我还是没看懂能帮忙讲解下么


  • 0
    administrators

    @francis 前者是后者的简写。两者的效果是一样的。


  • 0

    @胡子大哈 就是 我想问 为啥 这么写可以 这个是ES6的新特性还是什么?我要看的话应该哪查?


  • 0
    administrators

    @francis ES6 的新特性


  • 0

    @胡子大哈 在 #14 React.js 加载、刷新数据 - 高阶组件 中说:

    ES6 的新特性

    好的好的 谢谢啊 感觉问这些东西很弱。。。


  • 0

    const loadAndRefresh = (url)=>{
      return (WrappedComponent)=>class extends Component{
          constructor(props) {
          super(props);
          this.state = {
            content:'数据加载中...'
          }
        }
        
        componentDidMount(){
          this.refresh();
        }
        
        refresh=()=>{
          this.setState({content:'数据加载中...'});
          var getUrl=getData(url);
          getUrl.then((res)=>{
            this.setState({content:res});
          })
        }
        
        render(){
          return <WrappedComponent refresh={this.refresh} content={this.state.content} {...this.props} /> 
        }
      }
    }
    

  • 0

    const loadAndRefresh = (url)=>{
        return function(wrapedComponent){
          class wrapComponent extends Component{
            constructor(){
              super();
              this.state={
                content:'数据加载中...'
              }
            }
            componentWillMount(){
              this.refresh();
            }
            refresh(){
              getData(url).then((data)=>{
                this.setState({
                  content:data
                })
              })
            }
            render(){
              return(
                <wrapedComponent content={this.state.content} refresh={this.refresh.bind(this)} {...this.props} />  
              )
            }
          }
          return wrapComponent;
        }
      }
    

    @胡子大哈 为什么总是报返回的组件应该包裹传入的组件,我明明已经使用了


  • 0
    administrators

    @小弋 组件要用大写字母


  • 0

    @胡子大哈 谢谢,大意了


  • 0

    所有传给 loadAndRefresh 返回的组件的 props 要原封不动传给被包裹的组件。

    这句不是太明白什么意思


登录后回复
 

与 ScriptOJ 的连接断开,我们正在尝试重连,请耐心等待