哪个组件应该控制下部组件的加载状态?

时间:2016-06-15 08:16:26

标签: ajax reactjs loading state

假设我有这些组件:

Translator
  TranslationList

Translator确定翻译上下文,具有翻译功能。 TranslationList必须显示这些“视觉状态”:加载,结果列表,没有结果。

Translator在页面周围移动(一个实例):在对输入进行聚焦时,它会在“下方”移动并给出一个带有建议的下拉列表。

因此,每次移动时,都必须:

  • 显示正在加载翻译
  • 显示翻译列表或没有结果消息。

所以我的问题是:

哪个组件应该控制“加载”视觉状态?

如果Translator组件控制它,则必须将loading=true translations=[]作为道具传递给Translation列表。然后它必须使用新道具loading=false translations=[...]再次重新渲染它。这似乎有点违反直觉,因为loading感觉就像TranslationList组件的状态。

如果我们TranslationList组件有loading状态,那么它还必须有translate个方法,这意味着我必须通过translate函数作为道具。然后我会将translationsloading作为状态。这一切都变得有点混乱,因为现在它必须还接收要翻译的字符串,上下文。

我也不希望有单独的组件来加载消息,没有结果消息。我宁愿将这些保留在TranslationList内,因为这3个共享相同的包装<div class="list-group"></div>

也许在这两个组件之间应该还有一个组件,只负责提取翻译数据?

2 个答案:

答案 0 :(得分:2)

转换程序组件应控制较低组件列表组件的加载状态。保持加载和转换逻辑,但在帮助下将它包装在一个高位组件中,你应该放置大部分逻辑。链接HOC https://www.youtube.com/watch?v=ymJOm5jY1tQ

&#13;
&#13;
const translateSelected = wrappedComponent =>
  //return Translator component
  class extends React.Component {
  state = {translatedText: [], loading:true}
  componentDidMount(){
    fetch("text to translate")
      .then(transText => this.setState({translatedText: transText, loading: false}))
  }
    render() {
    const {translatedText} = this.state
    return <WrappedComponent {..this.props} {...translatedText}
    }
  }

  const Translator_HOC = translateSelected(Translator);
&#13;
&#13;
&#13;

答案 1 :(得分:2)

您可以引入更高阶组件来控制加载状态和TranslationList的切换。这样您就可以将加载显示与TranslationList分开,因为它是关注的问题。这也允许您在其他区域使用HOC。

Translator可以作为“容器”组件来执行数据提取/传递。

例如:

// The Loadable HOC
function Loadable(WrappedComponent) {
  return function LoadableComponent({ loaded, ...otherProps }) {
    return loaded 
      ? <WrappedComponent {...otherProps} />
      : <div>Loading...</div>
  }
}

// Translation list doesn't need to know about "loaded" prop
function TranslationList({ translations }) {
  return (
    <ul>
      {
        translations.map((translation, index) =>
          <li key={index}>{translation}</li>                   
        )
      }
    </ul>
  )
}

// We create our new composed component here.
const LoadableTranslationList = Loadable(TranslationList)

class Translator extends React.Component {
  state = {
    loaded: false,
    translations: []
  }

  componentDidMount() {
    // Let's simulate a data fetch, typically you are going to access 
    // a prop like this.props.textToTranslate and then pass that to 
    // an API or redux action to fetch the respective translations.
    setTimeout(() => {
      this.setState({
        loaded: true,
        translations: [ 'Bonjour', 'Goddag', 'Hola' ]
      });
    }, 2000);
  }

  render() { 
    const { loaded, translations } = this.state;
    return (
      <div>
        <h3>Translations for "{this.props.textToTranslate}"</h3>
        <LoadableTranslationList loaded={loaded} translations={translations}  />
      </div> 
    )  
  }  
}

ReactDOM.render(<Translate textToTranslate="Hello" />)

在此处运行示例:http://www.webpackbin.com/NyQnWe54W