首页 > 解决方案 > 在 API 调用后更改元素的状态以显示组件数组

问题描述

我最近拿起了 Next.js,在进入任何后端之前,我查看了 React 和许多需要它的东西。

简而言之,我构建了一个表单,它将接受用户的输入,在 API 中使用它并返回一个 JSON 对象,它将编辑我稍后将展示的一些组件。所以我使用了状态。我使用辅助变量来设置布尔状态,一旦我的组件将被编辑,该状态将设置为 true。现在,我的组件存储在一个数组中,我将在稍后对其进行编辑后显示。这是代码

为避免混淆,showResults 是另一种按预期工作的状态。我的问题是 showMatch 和 setShowMatch

function Form() {

    // adding state to the HeadingText Component to hide it once the user presses the Search button
    const [showResults, setShowResults] = React.useState(true)
    
    // adding state to the auxiliary variable to show my array later after edit
    const [showMatch, setShowMatch] = React.useState(false)

    let matches = []

    // adding the form handling section, with async event to query the API
    const registerUser = async event => {
        event.preventDefault() // don't redirect the page

        // hiding the Component HeadingText, so we show only the data of the games
        setShowResults(false)

        // calling the API in api/register, passing the link of the game or anything we would like to pass
        const res = await fetch('/api/register', {
            body: JSON.stringify({ matchLink: event.target.matchLink.value }),
            headers: { 'Content-Type': 'application/json' },
            method: 'POST'
        })

        //querying the real API, printing out the result
        const result = await res.json()
        console.log(result)

        //preparing my array of components
        for (let i = 0; i < 3; i++) {
            matches.push(<Match
                title = { `game   ${i} `}
                nOfGame = {i}
                game = {result.rounds[i]}
            />);
        }

        setShowMatch(true);
        console.log('I have changed the state, I check if it is true or false, if true: print my array, else: print null')
        console.log(showMatch ? matches : null)
        console.log('I will print my array to double check it\'s value')
        console.log(matches)
    }

    return (
        <>
            { /* Showing or not the component Heading Text */ }
            { showResults ? <HeadingText /> : null }
            
            <div className="form-container">
                <form onSubmit={registerUser}>
                    <input type="text" name="matchLink" id="textFiledId" placeholder="insert a demo" />
                    <input type="submit" value="Search" name="subDemo" />
                </form>
            </div>

            { /* Showing or not the component of the match */ }
            <div className="match-holder">
                { showMatch ? matches : null } 
            </div>

            <p>{matches.length}</p> {/* This should be 0 */ }
        </>
    )
}

export default Form

我不明白我如何能够显示我的组件数组,因为控制台中的这条消息https://imgur.com/a/7JP7Jmy告诉我我的数组充满了组件。我 100% 确定我遗漏了一些东西,但是在浏览了 React 的状态文档一段时间后,我找不到有帮助的示例

(我看过正确修改 React.js 中状态数组的问题

标签: arraysreactjsnext.jsstate

解决方案


您在组件中使用本地非状态变量matches,这意味着无论您如何在registerUser函数中更新它,每次有状态变量更新时,它都会触发重新渲染并matches再次初始化为[]

你需要的是一个初始化为 的新状态变量[],你可以在你的registerUser函数中设置它。除非明确更改,否则它将在重新渲染时保留其值。

将组件存储在 state 中会影响性能,而不是将props提到的组件数组所需的存储为 state 中的对象数组并使用它来渲染组件。

这是一个示例实现

function Form() {

    // adding state to the HeadingText Component to hide it once the user presses the Search button
    const [showResults, setShowResults] = React.useState(true)

    const [matches, setMatches] = React.useState([])

    // adding the form handling section, with async event to query the API
    const registerUser = async event => {
        event.preventDefault() // don't redirect the page

        // hiding the Component HeadingText, so we show only the data of the games
        setShowResults(false)

        // calling the API in api/register, passing the link of the game or anything we would like to pass
        const res = await fetch('/api/register', {
            body: JSON.stringify({ matchLink: event.target.matchLink.value }),
            headers: { 'Content-Type': 'application/json' },
            method: 'POST'
        })

        //querying the real API, printing out the result
        const result = await res.json()
        console.log(result)

        let nmatch = []

        //preparing my array of components
        for (let i = 0; i < 3; i++) {
            nmatch.push({
                title: `game   ${i} `
                nOfGame: i
                game: result.rounds[i]
            });
        }
        setMatches(nmatch)
    }

    return (
        <>
            { /* Showing or not the component Heading Text */ }
            { showResults ? <HeadingText /> : null }

            <div className="form-container">
                <form onSubmit={registerUser}>
                    <input type="text" name="matchLink" id="textFiledId" placeholder="insert a demo" />
                    <input type="submit" value="Search" name="subDemo" />
                </form>
            </div>

            { /* Showing or not the component of the match */ }
            <div className="match-holder">
                { matches.length > 0 && (
                  matches.map(m => (
                    <Match
                      key={m.title}
                      {...m}
                    />
                  ))
                )}
            </div>
            <p>{matches.length}</p> {/* This should be 0 */ }
        </>
    )
}

export default Form

推荐阅读