使用钩子将状态提升到React应用程序中的主要组件

时间:2019-04-06 11:50:25

标签: javascript reactjs react-hooks

我正在学习reactjs并尝试实现一些小东西进行练习。这个想法很简单,可以将记录(feedbackTasks)添加到数据库中并列出这些记录(第一次加载页面时,后来添加新记录时)。请参见下图。

enter image description here

主要成分为ManageFeedbackTasks。我将feedbackTask项的列表保持在其状态(st_feedbackTaskList)中。该列表的更新通过add_to_st_feedbackTask函数执行。如果是第一次生成此列表,则所有提取的数据(来自PrintFeedbackTasks组件)都将设置为st_feedbackTaskList。如果不是,则仅将添加的项目(来自ShowAddingFeedbackTaskForm)插入列表。

export function ManageFeedbackTasks() {
    const [st_feedbackTaskList, setFeedbackTaskList] = useState([]);

    const add_to_st_feedbackTask = (data) => {

        if (st_feedbackTaskList.length == 0) {
            setFeedbackTaskList(data);
        } else {
            const { id, title, description } = data;
            setFeedbackTaskList([...st_feedbackTaskList, { id, title, description }]);
        }
    }

    return (
        <>
            <ShowAddingFeedbackTaskForm onAddingItem={add_to_st_feedbackTask} />
            <PrintFeedbackTasks onListingFeedbackTasks={add_to_st_feedbackTask} feedbackTasks={st_feedbackTaskList} />
        </>
    );
}

下面是PrintFeedbackTasks函数。该函数从主要组件feedbackTasks接收ManageFeedbackTasks列表。首次使用fetchFeedbackTasks从数据库中获取此列表。在fetchFeedbackTasks内部,props.onListingFeedbackTasks(response.data)将获取的列表发送回主要组件以更新状态(st_feedbackTaskList)。

const PrintFeedbackTasks = (props) => {    
    const [st_isInitialized, setInitialized] = useState(false);    

    const fetchFeedbackTasks = () => {
        axios.get('api/FeedbackTask/Index')
            .then(response => props.onListingFeedbackTasks(response.data))
            .catch(error => console.log(error));
    }    

    useEffect(() => {
        if (!st_isInitialized) {
            fetchFeedbackTasks();
        }
        setInitialized(true);
    });

    return (
        <React.Fragment>
           {
                props.feedbackTasks.map(taskItem =>....
           }
        </React.Fragment>
    );
}

下面的组件显示“添加”表单并处理表单提交。添加新项目后,该新项目将再次使用props.onAddingItem发送回主要组件。

const ShowAddingFeedbackTaskForm = (props) => {
    const [st_title, setTitle] = useState('');
    const [st_description, setDescription] = useState('');

    const handleSubmit = async (event) => {
        event.preventDefault();
        await axios(...)
        .then(function (response) {
                setTitle('');
                setDescription('');

            //This will update the list of the feedback task in the main component
                props.onAddingItem({
                   id: response.data,
                   title: st_title,
                   description: st_description
                });

            //GET THE ID HERE
            console.log(response.data);

        }).catch(function (error) {
            console.log(error);
        });
    }


    return (
        <form onSubmit={handleSubmit}>
            <input
                placeholder="Title..."
                type="text"
                value={st_title}
                onChange={(event) => setTitle(event.target.value)}
            />
            <input
                placeholder="Description..."
                type="text"
                value={st_description}
                onChange={(event) => setDescription(event.target.value)}
            />
            <button>Add Feedback Task</button>
        </form>
    );
}

我想知道这种提升和管理国家的方式是否可靠。有任何改进代码的建议吗?另外,我想知道是否应该将这些组件放到自己的页面中(例如,一页或添加一条记录,另一页用于列出)。在react世界中,这更有意义吗?

1 个答案:

答案 0 :(得分:1)

将状态提升到父级的想法是正确的。但是,由于您的代码结构,您可能会导致大量重新渲染,并且可以在解决方案中进行一些性能优化。还有一件事是,与其在PrintFeedbackTasks组件中获取feedbackTasks,不如在父类本身中完成它。 useEffect还带有第二个参数,您可以使用该参数在初始安装时执行

您也可以使用useCallback挂钩来记住功能。

ManageFeedbackTasks

export function ManageFeedbackTasks() {
    const [st_feedbackTaskList, setFeedbackTaskList] = useState([]);

    const fetchFeedbackTasks = useCallback(() => {
        axios.get('api/FeedbackTask/Index')
            .then(response => props.onListingFeedbackTasks(response.data))
            .catch(error => console.log(error));
    }, []);    

    useEffect(() => {
        fetchFeedbackTasks();
    }, []);

    const add_to_st_feedbackTask = useCallback((data) => {

        setFeedbackTaskList(prevTaskList => {
          if (prevTaskList.length == 0) {
            return data;
          } else {
            const { id, title, description } = data;
            return [...prevTaskList, { id, title, description }];
          }
        });
    }, [])

    return (
        <>
            <ShowAddingFeedbackTaskForm onAddingItem={add_to_st_feedbackTask} />
            <PrintFeedbackTasks onListingFeedbackTasks={add_to_st_feedbackTask} feedbackTasks={st_feedbackTaskList} />
        </>
    );
}

PrintFeedbackTasks

const PrintFeedbackTasks = (props) => {    

    return (
        <React.Fragment>
           {
                props.feedbackTasks.map(taskItem =>....
           }
        </React.Fragment>
    );
}

就拆分显示和更新TaskList的想法而言,它是产品决定,可以根据用户一次填写字段列表的时间来决定