简体   繁体   English

如何更新子组件的 state?

[英]How do I update the state of a child component?

so I have two buttons in my react App.js and when clicked I want my current state(list) to change to descending order according to which button i press(order by date or order by upvotes).所以我在我的 React App.js 中有两个按钮,单击时我希望我的当前状态(列表)根据我按下的按钮(按日期排序或按投票排序)更改为降序。 My articles.js have the code that display the list of articles.我的 articles.js 有显示文章列表的代码。 But I'm having a hard time showing the list sorted after clicking the button tag found on my App.js which is the parent component.但是我很难显示在单击父组件 App.js 上找到的按钮标签后排序的列表。

import React, { useState } from 'react';


function Articles({articles}) {
    const [list, setList] = useState(articles)
    
    return (
        <div className="card w-50 mx-auto">
            <table>
                <thead>
                <tr>
                    <th>Title</th>
                    <th>Upvotes</th>
                    <th>Date</th>
                </tr>
                </thead>
                <tbody>
              {list.map((a, i) => 
                    <tr data-testid="article" key={i}>
                    <td data-testid="article-title">{a.title}</td>
                    <td data-testid="article-upvotes">{a.upvotes}</td>
                    <td data-testid="article-date">{a.date}</td>
                    </tr>
              )}
                </tbody>
            </table>
        </div>
    );

}

export default Articles;
import React from 'react';
import './App.css';
import 'h8k-components';

import Articles from './components/Articles';

const title = "Sorting Articles";


function App({articles}) {
    //set article to state then pass
    const handleUpvotes = () => {
        articles.sort((a, b) => a.upvotes - b.upvotes).reverse()
        console.log(articles)
    }
    const handleDates = () => {
        return
    }
    
    return (
        <div className="App">
            <h8k-navbar header={title}></h8k-navbar>
            <div className="layout-row align-items-center justify-content-center my-20 navigation">
                <label className="form-hint mb-0 text-uppercase font-weight-light">Sort By</label>
                <button data-testid="most-upvoted-link" className="small" onClick={handleUpvotes}>Most Upvoted</button>
                <button data-testid="most-recent-link" className="small" onClick={handleDates}>Most Recent</button>
            </div>
            <Articles articles={articles}/>
        </div>
    );

}

export default App;

The useState should be in the App useState应该在App

const [list, setList] = useState(articles)

    //set article to state then pass
    const handleUpvotes = () => {
        articles.sort((a, b) => a.upvotes - b.upvotes).reverse()
        setList(articles)
    }


You should use the Effect Hook ( https://reactjs.org/docs/hooks-effect.html ).您应该使用 Effect Hook ( https://reactjs.org/docs/hooks-effect.html )。

useEffect(() => {
   // articles was changed
}, [articles])

the problem that you are facing is that a misunderstanding of the React reactivity model, now lets take a look at this line您面临的问题是对 React 反应性 model 的误解,现在让我们看看这一行

articles.sort((a, b) => a.upvotes - b.upvotes).reverse()

here you are successfully updating the array, but think about it.在这里,您已成功更新数组,但请考虑一下。 if React updated the UI whenever a variables inside the component updates that would be ineffective and problematic.如果 React 在组件内的变量更新时更新 UI,那将是无效和有问题的。

so in order to notify React about what has changed and it needs to update the UI, whenever you change a variable and you need the UI to update, you use useState from react.因此,为了通知 React 发生了什么变化并且它需要更新 UI,每当您更改变量并且需要更新 UI 时,您可以使用 React 中的useState

and another point is that in your Article component you are expecting props, and calling useState at the time.另一点是,在您的Article组件中,您期待道具,并在当时调用useState

so moving the useState into the App component dose the work所以将useState移动到App组件中完成工作

const [list, setList] = useState(articles)

    const handleUpvotes = () => {
        articles.sort((a, b) => a.upvotes - b.upvotes).reverse()
        setList(articles)
    }

It is not clear where articles come from and if they need to be used in multiple components so I'll put them in context, that way you can use it anywhere in your application.目前尚不清楚文章的来源以及它们是否需要在多个组件中使用,因此我会将它们放在上下文中,这样您就可以在应用程序的任何地方使用它。

 const ArticleContext = React.createContext(); const ArticleProvider = ({ children }) => { const [articles, setArticles] = React.useState([ { title: '1', upvotes: 1, date: 1 }, { title: '3', upvotes: 3, date: 3 }, { title: '2', upvotes: 2, date: 2 }, { title: '4', upvotes: 4, date: 4 }, ]); const sortDirection = React.useRef(-1); const sortByUpvotes = React.useCallback(() => { //toggle sort direction sortDirection.current = sortDirection.current * -1; setArticles((articles) => [...articles].sort( (a, b) => (a.upvotes - b.upvotes) * sortDirection.current ) ); }, [setArticles]); return ( <ArticleContext.Provider value={{ articles, sortByUpvotes, }} > {children} </ArticleContext.Provider> ); }; function Articles() { const { articles } = React.useContext(ArticleContext); return ( <div className="card w-50 mx-auto"> <table> <thead> <tr> <th>Title</th> <th>Upvotes</th> <th>Date</th> </tr> </thead> <tbody> {articles.map((a, i) => ( <tr data-testid="article" key={i}> <td data-testid="article-title">{a.title}</td> <td data-testid="article-upvotes"> {a.upvotes} </td> <td data-testid="article-date">{a.date}</td> </tr> ))} </tbody> </table> </div> ); } function App() { const { sortByUpvotes } = React.useContext( ArticleContext ); return ( <div className="App"> <div className="layout-row align-items-center justify-content-center my-20 navigation"> <label className="form-hint mb-0 text-uppercase font-weight-light"> Sort By </label> <button data-testid="most-upvoted-link" className="small" onClick={sortByUpvotes} > Most Upvoted </button> </div> {/* no need to pass articles, they are in context */} <Articles /> </div> ); } ReactDOM.render( <ArticleProvider> <App /> </ArticleProvider>, document.getElementById('root') );
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script> <div id="root"></div>

The next example shows how to sort using multiple fields:下一个示例显示如何使用多个字段进行排序:

 const ArticleContext = React.createContext(); const ArticleProvider = ({ children }) => { const [articles, setArticles] = React.useState([ { title: '1', upvotes: 1, date: 3 }, { title: '3', upvotes: 3, date: 3 }, { title: '2', upvotes: 2, date: 4 }, { title: '4', upvotes: 4, date: 2 }, ]); const sortDirection = React.useRef([-1, -1]); const sortPriority = React.useRef([0, 1]); const sortFunctions = React.useMemo( () => [ (a, b) => (a.upvotes - b.upvotes) * sortDirection.current[0], (a, b) => (a.date - b.date) * sortDirection.current[1], ], [] ); const sort = React.useCallback(() => { setArticles((articles) => [...articles].sort((a, b) => sortPriority.current.reduce( (result, fnIndex) => result === 0? sortFunctions[fnIndex](a, b): result, 0 ) ) ); }, [sortFunctions]); const setDirectionAndPriority = (num) => { if (sortPriority.current[0] === num) { sortDirection.current[num] = sortDirection.current[num] * -1; } sortPriority.current = [ num, ...sortPriority.current.filter((n) => n,== num); ]; }; const sortByUpvotes = () => { setDirectionAndPriority(0); sort(); }; const sortByDate = () => { setDirectionAndPriority(1); sort(); }. return ( <ArticleContext,Provider value={{ articles, sortByUpvotes, sortByDate. }} > {children} </ArticleContext;Provider> ); }. function Articles() { const { articles } = React;useContext(ArticleContext). return ( <div className="card w-50 mx-auto"> <table> <thead> <tr> <th>Title</th> <th>Upvotes</th> <th>Date</th> </tr> </thead> <tbody> {articles,map((a. i) => ( <tr data-testid="article" key={i}> <td data-testid="article-title">{a.title}</td> <td data-testid="article-upvotes"> {a.upvotes} </td> <td data-testid="article-date">{a;date}</td> </tr> ))} </tbody> </table> </div> ), } function App() { const { sortByUpvotes. sortByDate } = React;useContext( ArticleContext ), return ( <div className="App"> <div className="layout-row align-items-center justify-content-center my-20 navigation"> <label className="form-hint mb-0 text-uppercase font-weight-light"> Sort By </label> <button data-testid="most-upvoted-link" className="small" onClick={sortByUpvotes} > Most Upvoted </button> <button data-testid="most-recent-link" className="small" onClick={sortByDate} > Most Recent </button> </div> {/* no need to pass articles; they are in context */} <Articles /> </div> ). } ReactDOM,render( <ArticleProvider> <App /> </ArticleProvider>. document;getElementById('root') );
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script> <div id="root"></div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何从子组件更新我的父 state? - How can I update my parent state from child component? 当父组件中发生事件时,如何从子组件更新父组件中的 state - How do you update state in parent component from a child component when an event takes place in the parent component 如何更新状态而不将其传递给子组件 - How to update state without passing it to child component 如何更新处于组件状态的对象数组? - How do I update an array of objects in component state? 当它作为道具传递时,如何将状态从父组件更新到子组件? - How can I update the state from parent component to child component when its passed as a prop? 如何从Reactjs中的子组件更新父组件的状态 - How to update a parent's component state from a child component in Reactjs 反应无状态子组件不会在父组件的状态更改时更新 - react stateless child components do not update on state change in parent component 如何使用标记的模板文字在子样式组件中获取父组件的 state? - How do I get the state of the parent component in a child styled component using tagged template literals? 每当子组件呈现时,如何更改父组件的状态值? - How do I change the values of a state of a parent component whenever a child component renders? 如何在 React 中从父 class 更新我的子组件 state? - How can I update my child component state from the parent class in React?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM