【问题标题】:List fails to see updated state of array列表无法查看数组的更新状态
【发布时间】:2020-02-06 11:59:43
【问题描述】:

预期的行为:两次渲染。最初您会看到一个加载器,当在后台成功获取学生时,加载器会更改为一个包含学生的列表。

我忽略了什么?

初始渲染

  1. 使用状态将elem设置为显示(<Loader/>)和students数组(一个用于测试的初始对象)

  2. 获取studentsuseEffect中的对象数组

  3. 在成功获取更新状态时 - 将 students 设置为 fetched 数组,将 elem 设置为 renderList,这将使用 students 内容填充其列表项

  4. console.log(students.length) 此时显示 1 - 正确

  5. 状态已更新,因此重新渲染

第二次渲染

  1. console.log(students.length) 显示 49 - students 正确更新

为什么? - 7. renderList 看到 students 的初始值(1 个对象)

是否因为要显示的elem 及其内容(students)处于状态,并且它们同时在useEffect 中更新?

<!-- language: lang-js -->

all imports

export default function AttendanceSingleClass(props) {

    const {classId, groupId} = props.route.params.classObj;
    const [students, _setStudents] = useState([{sId:1,name:'foo',fname:'bar'}]);
    const [elem, _setElem] = useState(<Loader/>);

    useEffect(() => {

            async function _getStudentsList() {
                try {
                    const students = await api.getStudentsList(groupId, classId);
                    _setStudents(students);
                    _setElem(renderList)
                } catch (e) {
                    console.log(e)
                }
            }
            _getStudentsList();
        },[classId]);

    const ListEl = (props) => {
        return (
            <View>..contents of list item...</View>
        )
    }

    const renderList = () => {
        return (
            <View>
                <FlatList
                    data={students}
                    extraData={students}
                    keyExtractor={item => item.sId}
                    renderItem={({item}) => <ListEl item={item} />}
                />
            </View>
        );
    }

    console.log(students.length);

    return elem;
}

经过一些实验,我尝试将 students 数组作为 prop 传递给 renderList - 有效。但我仍然不明白为什么它在全局范围内看到 students,但只是在初始值而不是在更新状态(如上所示)。

<!-- language: lang-js -->

export default function AttendanceSingleClass(props) {

    (...)
    useEffect(() => {

            async function _getStudentsList() {
                try {
                     _setElem(renderList(students))
                } 
            }
            _getStudentsList();
        }, [classId]);

    const renderList = (students) => {
        return (...);
    }

    (...);

}

【问题讨论】:

    标签: reactjs react-native react-hooks


    【解决方案1】:

    我建议选择不同的方法。将组件或渲染函数存储在状态中感觉是一种不好的做法,同时已经知道何时渲染哪个。

    例如我喜欢像这样使用loading 状态:

    export default function AttendanceSingleClass(props) {
      const { classId, groupId } = props.route.params.classObj;
      const [students, _setStudents] = useState([{ sId: 1, name: 'foo', fname: 'bar' }]);
      const [loading, _setLoading] = useState(true);
    
      useEffect(() => {
        _setLoading(true);
    
        async function _getStudentsList() {
          try {
            const students = await api.getStudentsList(groupId, classId);
            _setStudents(students);
            _setLoading(false);
          } catch (e) {
            console.log(e);
          }
        }
    
        _getStudentsList();
      }, [classId]);
    
      const ListEl = (props) => {
        return (
          <View>..contents of list item...</View>
        );
      };
    
      // early return the <Loader /> component when loading is true
      if (loading) {
        return <Loader />;
      }
    
      return (
        <View>
          <FlatList
            data={students}
            extraData={students}
            keyExtractor={item => item.sId}
            renderItem={({ item }) => <ListEl item={item} />}
          />
        </View>
      );
    }
    

    【讨论】:

    • 聪明,似乎更容易理解,谢谢!尽管如此,为什么students 数组在其更新状态下没有看到,这仍然让我感到困扰;
    • 如果你可以创建一个代码沙盒或类似的东西,我们可能会解决这个问题:-)
    猜你喜欢
    • 2018-06-06
    • 2021-09-09
    • 2021-04-03
    • 1970-01-01
    • 2020-11-26
    • 2018-08-07
    • 1970-01-01
    • 1970-01-01
    • 2023-01-30
    相关资源
    最近更新 更多