【问题标题】:How to use the data from parent component to be the useState of child component?如何使用父组件的数据作为子组件的useState?
【发布时间】:2021-06-12 02:22:41
【问题描述】:

我在 react js 中有一个组件来处理用户是否创建帖子。我还使用来自父组件的数据来显示用户的详细信息。就像用户的用户名一样。我遇到了问题,因为我找不到将来自组件父级的用户名分配为 useState 的一部分的方法。该值存在,但在用户提交数据后,用户名名称不包括在内。 您能向我解释或帮助我为什么价值不存在吗?

Parent Component    
  const userDetails = useSelector((state) => state.userLogin);

const { userData } = userDetails;

  const classes = useStyles();

  useEffect(() => {
    if (userDetails) {
      history.push();
    }
  }, [history, userDetails]);

  return (
    <FormContainer>
      <Container component='div' className={classes.homepageContainer}>
        <Grid item xs={12}>
          <Container component='div' className={classes.userFeedCard}>
            <Card className={classes.userPostFeedCard}>
              <UserPost userData={userData} />
            </Card>
          </Container>
        </Grid>
      </Container>
    </FormContainer>
  );
};

Child Component
const UserPost = ({ userInfo }) => {
  
  const [postInfo, setPostInfo] = useState({
    username: userInfo.username,
    description: '',
  });

  const handlePost = async (e) => {
    e.preventDefault();
    console.log(postInfo);
  };

  return (
    <Container
      component='div'
      className={classes.userPostContainer}
      style={{ padding: '0', margin: '0' }}
    >
      <Card className={classes.userPostCard} style={{ boxShadow: 'none' }}>
        <CardContent style={{ padding: '0 0 1.5em 0' }}>
          <form noValidate onSubmit={handlePost}>
            <Grid container>
              <Grid item xs={12}>
                <TextField
                  variant='outlined'
                  id='description'
                  name='description'
                  type='text'
                  value={postInfo.description}
                  onChange={handleChange}
                  placeholder={`What's on your mind, ${
                    userInfo && userInfo.username
                  }`}
                  fullWidth
                  InputLabelProps={{
                    classes: {
                      root: classes.label,
                      focused: classes.focused,
                    },
                  }}
                  InputProps={{
                    className: classes.textfieldBg,
                    classes: {
                      root: classes.cssOutlinedInputBg,
                      focused: classes.cssFocused,
                      notchedOutline: classes.NonotchedOutline,
                    },
                  }}
                />
              </Grid>
              <Grid
                xs={12}
                container
                className={classes.postPhotoContainer}
                style={{ padding: '0' }}
              >
                <Grid xs={2} style={{ padding: '0', margin: '0' }}>
                  <Button
                    type='submit'
                    variant='contained'
                    startIcon={<SendIcon />}
                    style={{}}
                  >
                    Upload
                  </Button>
                </Grid>
              </Grid>
            </Grid>
          </form>
        </CardContent>
      </Card>
    </Container>
  );
};

【问题讨论】:

  • 你总是想要一个“单一的事实来源”,所以你不应该在 state 中复制 props。只需直接使用道具中的userInfo
  • 您在此处所做的操作将postInfo 状态的初始值 设置为包含来自道具的用户名。它不会响应父组件中的任何更改。
  • HomePage 中的userInfo 状态也是不必要的数据复制。你已经从 Redux 获得了这些数据。够了!它不应该存储在状态中。
  • 感谢@LindaPaiste 的建议

标签: reactjs


【解决方案1】:

单一真理来源

应用中的每条数据都应该只有一个存储和更新的地方。您可以使用props 在组件之间传递这些数据。

当您在多个组件的state 中有数据时,您可能会得到不同步的数据。 UserPost 组件使用来自 props 的 userInfo 来设置 username初始值,但它不会响应任何更改。

您可以通过删除大量不必要的重复数据来简化代码。

HomePage 从 Redux 访问当前用户。它不需要任何组件状态。

const HomePage = () => {
  const userInfo = useSelector((state) => state.userLogin?.userData);

  const classes = useStyles();

  return (
    /*...*/
  );
}

UserPost 需要一些本地状态才能存储description。它从 props 中获取userInfo,并且不应该在其状态下复制用户。只需直接从道具访问它。 (注意:你可以把useSelector移到这里,从Redux获取用户)

postInfo 就是我们所说的“派生数据”。它是你可以从道具和状态中获得的东西。您可以在组件的顶层或handlePost 回调中定义此const。如果它只被handlePost 使用,那么我会把它放在那里。

const UserPost = ({ userInfo }) => {

  // description is a state
  const [description, setDescription] = useState('');

  const handlePost = async (e) => {
    e.preventDefault();

    // variable derived from props and state
    const postInfo = {
      username: userInfo.username, // from props
      description, // from state
    };

    console.log(postInfo);
  };

  return (
    /* ... */
  );
}

在你的TextField

value={description}
onChange={(e) => setDescription(e.target.value)}

【讨论】:

  • 非常感谢,这对我有很大帮助!我按照你说的做了一些修改。
猜你喜欢
  • 2021-11-27
  • 1970-01-01
  • 2020-09-22
  • 2017-05-28
  • 1970-01-01
  • 1970-01-01
  • 2019-05-04
  • 2019-02-19
  • 2017-06-13
相关资源
最近更新 更多