【问题标题】:useState won't update the state when I set it in react当我在 react 中设置 useState 时,它​​不会更新状态
【发布时间】:2021-06-30 20:44:47
【问题描述】:

我需要使用反应路由器渲染一个具有路由的组件。第一个组件有一个按钮,单击该按钮时需要呈现另一个组件,该组件具有从第一个组件传入的状态。页面重定向但不加载。我想要的第一个组件的所有数据都被传入,但是当我使用 setProfile(p) 时它不会设置状态。成员组件中的所有其他 console.log() 都显示了我期望的所有数据,但它不会使用这些数据设置状态。

import {useLocation} from "react-router-dom";
    const Member = (props)=> {  
      const [user, setUser] = useState({});
      const [profile, setProfile] = useState({});

  const [user, setUser] = useState({});
  const { state } = useLocation();
  const [profile, setProfile] = useState({});
  const dispatch = useDispatch();
  const [list, setList] = useState([]);
  const [posts, setPosts] = useState([]);
  const [snInstance, setsnInstance] = useState({});
    
   // run effect when user state updates
    useEffect(() => {
  const doEffects = async () => {
    try {
    //  const p = await incidentsInstance.usersProfile(state.user, { from: accounts[0] });
    //  const a = await snInstance.getUsersPosts(state.user, { from: accounts[0] });

      if (state && state.user) {
        setUser(state.user);
      }

      const accounts = await MyWeb3.getInstance().getAccounts();
      setAccounts(accounts);
      console.log(accounts)
      const incidents = MyWeb3.getInstance().getContract(Incidents)
      const incidentsInstance = await MyWeb3.getInstance().deployContract(incidents);
      const sn = MyWeb3.getInstance().getContract(SocialNet)
      const snInstance = await MyWeb3.getInstance().deployContract(sn);
      setsnInstance(snInstance);
      const pro = socialNetworkContract.members[0]
      console.log(pro)
      const p = await incidentsInstance.usersProfile(pro, { from: accounts[0] });
      const a = await snInstance.getUsersPosts(pro, { from: accounts[0] });
      console.log(a)
      console.log(p)
      setProfile(p)

        } catch (e) {
      console.error(e)
    }
  }
    doEffects();
  }, [profile, state]);

  const socialNetworkContract = useSelector((state) => state.socialNetworkContract)

  return (
    <div class="container">

                <a target="_blank">Name : {profile.name}</a>

        {socialNetworkContract.posts.map((p, index) => {
          return <tr key={index}>
{p.message}
        </tr>})}
      </div>
  )
}

export default Member;

这是我要重定向的父组件

   const getProfile = async (member) => {
        const addr = dispatch({ type: 'ADD_MEMBER', response: member })
        console.log(member)
    }


  const socialNetworkContract = useSelector((state) => state.socialNetworkContract)

    
      return (
          <div>
            {socialNetworkContract.posts.map((p, index) => {
              return <tr key={index}>
    
      <button onClick={() => getProfile(p.publisher)}>Profile</button>
    
            </tr>})}
          </div>
      )
    }
export default withRouter(Posts);

当我没有需要从父组件传入数据的动态路由时,我让这个组件工作。它正在重定向。

我的 routes.js 看起来像

const Routes = (props) => {
  return (
      <Switch>

      <Route path="/member" exact component={Member} /> 
        <Route path="/posts" exact component={Posts} />
        <Redirect exact to="/" />
      </Switch>
    
  )
}

export default Routes

这是减速器

import { connect, useDispatch, useSelector } from "react-redux";
let init = {
    posts:[],
    post:{},
    profiles:[],
    profile:{},
    members:[],
    member:{}
}
export const socialNetworkContract = (state = init, action) => {
    const { type, response } = action;
    switch (type) {
        case 'ADD_POST':
            return {
                ...state,
                posts: [...state.posts, response]
            }
        case 'SET_POST':
            return {
                ...state,
                post: response
            }
        case 'ADD_PROFILE':
            return {
                ...state,
                profiles: [...state.profiles, response]
            }
        case 'SET_PROFILE':
            return {
                ...state,
                profile: response
            }
        case 'ADD_MEMBER':
            return {
                ...state,
                members: [...state.members, response]
            }
        case 'SET_MEMBER':
            return {
                ...state,
                member: response
            }

        default: return state
    }
};

【问题讨论】:

    标签: javascript reactjs react-redux react-router


    【解决方案1】:

    将dispatch({ type: 'ADD_MEMBER', response: member }) 与来自post 的publisher 属性的member 对象结合使用没有任何意义。该信息已经在您所在的州。您可能需要更好地normalizing your state,以便您可以在需要的地方选择它。


    您想使用 react-router-dom 中的 Link 组件导航到成员的个人资料页面。您的 Route 应该根据 URL 中的 id 或 username 属性呈现正确的配置文件。重定向时不要传递数据,只需转到正确的 URL。在该Member 页面上,您可以通过查找id 来从该州获取用户。

    在Posts:

    <Link to={`/member/${p.publisher.id}`}><button>Profile</button></Link>
    

    在Routes:

    <Route path="/member/:id" component={Member} />
    

    在Member:

    const Member = () => {
      const { id } = useParams();
    
      const profile = useSelector((state) =>
        state.socialNetworkContract.members.find((user) => user.id === id)
      );
    
      const dispatch = useDispatch();
    
      useEffect(() => {
        const doEffects = async () => {
          if ( ! profile ) {
            dispatch(loadUser(id));
          }
        };
        doEffects();
      }, [dispatch, profile, id]);
    

    【讨论】:

    • 您好,谢谢您的回答,我现在会尝试一些。我应该提到它正在与智能合约交互。 members 数组中的每个项目都只是一个字符串(以太坊地址),当页面加载时,它通过调用智能合约中的函数获取用户数据并将字符串作为参数传递。 console.log 中返回的对象显示了当组件被重定向到但它从不加载时它们应该做什么。
    • 您将 profile 作为您的 useEffect 的依赖项,但您正在调用 setProfile。您永远不想在效果中更新您的依赖项。
    • 这就是它不起作用的原因吗?我应该在哪里设置Profile?
    • 很难说。您的问题无法重现,因为您的代码缺少部分。 state 是什么? accounts 是什么? user 设置在哪里?我认为您的依赖项应该是 [user] 但我不知道。
    • accounts 是以太坊地址的 web3 实例。我已经更新了我的代码以包含它。智能合约发回我想要的变量。当页面重定向时,我的控制台中的所有对象都可以是 console.log()。
    猜你喜欢
    • 2020-03-27
    • 2023-02-26
    • 1970-01-01
    • 2019-08-10
    • 1970-01-01
    • 2020-05-12
    • 1970-01-01
    • 2020-11-10
    • 1970-01-01
    相关资源
    最近更新 更多