【问题标题】:How to render a list with data from inside a function using React?如何使用 React 从函数内部呈现包含数据的列表?
【发布时间】:2017-01-20 17:53:22
【问题描述】:

Source Code

对不起,如果标题令人困惑。但是如果你点击源代码你可以看到我有一个组件名称搜索。内部搜索是一个函数handleSearchSubmit,当用户单击渲染函数内部的搜索按钮时会激活该函数。现在我的问题是我现在想更新trackViewer 中的列表。每个列表项都应填充{title}<ul> 应称为{trackItems}。但无论我做什么,我似乎都能让列表更新。如果我不包括this,那么变量 trackItems 在渲染函数中是未定义的。那么我到底做错了什么?这应该是同一文件中的单独组件还是新文件?

【问题讨论】:

    标签: javascript ajax api reactjs web-applications


    【解决方案1】:

    据我了解,此处所需的行为是从 API 获取数据并在收到数据时显示它。 实现 React 的基本思想很重要。当且仅当它的状态或上游道具发生变化时,组件才会重新渲染。这就是你需要的。使用状态改变触发重新渲染。

    import React, { Component } from 'react';
    import { client_id } from './config';
    import 'isomorphic-fetch';
    import 'whatwg-fetch';
    import SC from 'soundcloud';
    import ReactDOM from 'react-dom';
    
    // This is not a good place for such data, all data should be encapsulated accordingly
    let search = "https://api.soundcloud.com/tracks?&client_id="+ client_id +"&limit=50&offset=0&q="+query;
    let tags = "https://api.soundcloud.com/tracks?linked_partitioning=1&client_id="+ client_id +"&limit=50&offset=0&tags=deep%20house";
    
    class Search extends Component{
    
        constructor(props){
            super(props);
    
            this.state = {
                value: '',
                // Moved trackTitle from above into the state
                trackTitle: []
            };
        };
    
        handleChange(event){
            event.preventDefault();
    
            this.setState({ value: event.target.value });
        }
    
        handleSearchSubmit(){
            event.preventDefault();
    
            // Create local scope buffer for trackTitles to store in state in the end
            let trackTitleBuffer = []
    
            // You can use shortened expression instead of client_id: client_id, hail ES2015!
            SC.initialize({ client_id });
    
            // You don't really need query variable, use state directly
            // Using arrow functions for readability
            fetch(search + this.state.value, { method:"GET" })
            .then(response => response.json())
            .catch(error => console.log(error))
            .then(json => {
                json.map(entity => trackTitleBuffer.push(entity.title))
               // And pour it all to the state.trackTitle
               // This is important, you only to want to re-render when you have all the track titles ready
               // If you pushed the track titles to the state one-by-one, every push would trigger a re-render
               // It might look cool as well as it might not
                this.setState({ trackTitle: trackTitleBuffer })
            })
            .catch(error => console.log(error))
        };
    
        render(){
            // Desctructuring the state
            const { trackTitle, value } = this.state
    
            return(
                <form>
                <input type="text" value={this.state.value} placeholder="Enter a Artist, Song, or Album.." onChange={event => this.handleChange(event)}/>
                <button type="button" onClick={() => this.handleSearchSubmit()}>Search</button>
                <div id="trackViewer">
                     <p>Results for: {value}</p>
                     <ul>{ trackTitle.map(title => <li key={title)}>{title}</li>) }</ul>
                </div>
                </form>
            )
        };
    };
    
    export default Search;
    

    【讨论】:

    • 感谢这个解决方案解决了重新渲染和列表问题。 .
    【解决方案2】:

    您的 trackItems 变量是未附加到您的类的局部变量,因此您无法通过渲染函数中的 this.trackItems 访问它

    const trackItems = trackTitle.map((titles) =>
                <li>{titles}</li>
            );
    

    所以快速修复,完全取消 trackItems 变量,而是按原样在渲染函数中运行该代码 sn-p:

    render(){
        return(
            <form>
            <input type="text" value={this.state.value} placeholder="Enter a Artist, Song, or Album.." onChange={this.handleChange}/>
            <button type="button" onClick={this.handleSearchSubmit}>Search</button>
            <div id="trackViewer">
                 <p>Results for: {this.state.value}</p>
                 <ul>{trackTitle.map((titles) =><li>{titles}</li>)}</ul>
            </div>
            </form>
        )
    }
    

    【讨论】:

    • 我更新了代码,以便您也可以看到它,但我尝试了您的建议,但仍然没有显示任何内容。在控制台中,我可以看到值是空的,所以应该显示一些东西。
    • 我实际上能够让它工作,但是发生了一个奇怪的错误。在我单击输入并输入内容之前,列表实际上不会显示结果。我怀疑这可能是因为它在表单标签内
    猜你喜欢
    • 2021-09-23
    • 2020-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-13
    • 1970-01-01
    相关资源
    最近更新 更多