内容的栏目 * @param int $category 0列表 1频道 2单页 3外链 * @return array */ function category_list($forumlist, $model = 0, $display = 0, $category = 0) { if (empty($forumlist)) return NULL; static $cache = array(); $key = $model . '-' . $display . '-' . $category; if (isset($cache[$key])) return $cache[$key]; if ($display) { foreach ($forumlist as $k => $val) { if (1 == $val['display'] && 1 == $val['type'] && $val['category'] == $category) { $cache[$key][$k] = $val; } } } else { foreach ($forumlist as $k => $val) { if (1 == $val['type'] && $val['category'] == $category) { $cache[$key][$k] = $val; } } } return empty($cache[$key]) ? NULL : $cache[$key]; } /** * @param $forumlist 所有版块列表 不分模型 * @param int $display 0全部CMS栏目 1在首页和频道显示内容的栏目 * @param int $category 0列表 1频道 2单页 3外链 * @return array */ function category_list_show($forumlist, $display = 0, $category = 0) { if (empty($forumlist)) return NULL; static $cache = array(); $key = $display . '-' . $category; if (isset($cache[$key])) return $cache[$key]; if ($display) { foreach ($forumlist as $k => $val) { if (1 == $val['display'] && 1 == $val['type'] && $val['category'] == $category) { $cache[$key][$k] = $val; } } } else { foreach ($forumlist as $k => $val) { if (1 == $val['type'] && $val['category'] == $category) { $cache[$key][$k] = $val; } } } return empty($cache[$key]) ? NULL : $cache[$key]; } /** * @param $forumlist 所有版块列表 * @return mixed BBS栏目数据(仅列表) 尚未开放bbs频道功能 */ function forum_list($forumlist) { if (empty($forumlist)) return array(); static $cache = array(); if (isset($cache['bbs_forum_list'])) return $cache['bbs_forum_list']; $cache['bbs_forum_list'] = array(); foreach ($forumlist as $_fid => $_forum) { if ($_forum['type']) continue; $cache['bbs_forum_list'][$_fid] = $_forum; } return $cache['bbs_forum_list']; } // 导航显示的版块 function nav_list($forumlist) { if (empty($forumlist)) return NULL; static $cache = array(); if (isset($cache['nav_list'])) return $cache['nav_list']; foreach ($forumlist as $fid => $forum) { if (0 == $forum['nav_display']) { unset($forumlist[$fid]); } } return $cache['nav_list'] = $forumlist; } ?>javascript - I can't understand why components with 'connect()' are stateful in react - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - I can't understand why components with 'connect()' are stateful in react - Stack Overflow

programmeradmin0浏览0评论

My question is just same as the title.

Let's say I wrote the following code.

class TODOList extends Component {  
  render() {
    const {todos, onClick} = this.props;
    return (
      <ul>
            {todos.map(todo =>
                <Todo 
                    key={todo.id}
                    onClick={onClick}
                    {...todo}
                />
             )}
      </ul>
    );
  }
}


const mapStateToProps = (state) => {  
  return {
    todos: state.todos
  }
}


const mapDispatchToProps = (dispatch) => {  
    return {
        onClick(data){
          dispatch(plete(data)) 
        }
    }
}


export default connect(mapStateToProps,mapDispatchToProps)(TODOList); 

Now, after the last line, this code will export the TODOList ponent with the state as props. It's not that it contains state, but just received state and will have them as 'props', just like the method name 'mapStateToProps' explains.

In the medium post(/@dan_abramov/smart-and-dumb-ponents-7ca2f9a7c7d0) written by Dan Abramov, container ponent handles data as state, and presentational property do as props. Isn't it a presentational ponent that deals with data as props? I'm stuck with the idea that the right container should be one like below.

class CommentList extends React.Component {
  this.state = { ments: [] };

  ponentDidMount() {
    fetchSomeComments(ments =>
      this.setState({ ments: ments }));
  }
  render() {
    return (
      <ul>
        {this.statements.map(c => (
          <li>{c.body}—{c.author}</li>
        ))}
      </ul>
    );
  }
}

I'm not sure why react-redux named the API 'mapStateToProps', when I tried to make 'stateful'(not handling data by property) container ponent

My question is just same as the title.

Let's say I wrote the following code.

class TODOList extends Component {  
  render() {
    const {todos, onClick} = this.props;
    return (
      <ul>
            {todos.map(todo =>
                <Todo 
                    key={todo.id}
                    onClick={onClick}
                    {...todo}
                />
             )}
      </ul>
    );
  }
}


const mapStateToProps = (state) => {  
  return {
    todos: state.todos
  }
}


const mapDispatchToProps = (dispatch) => {  
    return {
        onClick(data){
          dispatch(plete(data)) 
        }
    }
}


export default connect(mapStateToProps,mapDispatchToProps)(TODOList); 

Now, after the last line, this code will export the TODOList ponent with the state as props. It's not that it contains state, but just received state and will have them as 'props', just like the method name 'mapStateToProps' explains.

In the medium post(https://medium./@dan_abramov/smart-and-dumb-ponents-7ca2f9a7c7d0) written by Dan Abramov, container ponent handles data as state, and presentational property do as props. Isn't it a presentational ponent that deals with data as props? I'm stuck with the idea that the right container should be one like below.

class CommentList extends React.Component {
  this.state = { ments: [] };

  ponentDidMount() {
    fetchSomeComments(ments =>
      this.setState({ ments: ments }));
  }
  render() {
    return (
      <ul>
        {this.state.ments.map(c => (
          <li>{c.body}—{c.author}</li>
        ))}
      </ul>
    );
  }
}

I'm not sure why react-redux named the API 'mapStateToProps', when I tried to make 'stateful'(not handling data by property) container ponent

Share Improve this question edited Dec 17, 2018 at 2:20 Mohamed Ibrahim Elsayed 2,9743 gold badges26 silver badges46 bronze badges asked Dec 16, 2018 at 12:37 Now.ZeroNow.Zero 1,4093 gold badges18 silver badges31 bronze badges 1
  • "state" isn't a term specific to react, it's general to puter programming. It's a general term meaning remembered state of the system. en.wikipedia/wiki/State_(puter_science). Redux reducer state and ponent state are different things. – Andy Ray Commented Dec 17, 2018 at 2:26
Add a ment  | 

3 Answers 3

Reset to default 10

First of all these guidelines are not part of the bible
you should write code that is easy to reason about for YOU and your TEAM.

I think you are missing something, A redux Container is different than a react Container.
I mean, connect will create the container for you, it doesn't mean the wraped ponent is a Container.

Basically you can export both versions from the same file, the Container (connected version) and the presentation version (the none connected one).

Another thing that usually throw people off, is the name of the function and argument of mapStateToProps.
I prefer the name mapStoreToProps as in

map the redux store to the ponent's props.

the name state can be confusing when we are in the context of react.

Edit
As a followup to your ment:

I totally didn't know these two are actually different. Could you please tell me about more details

They are different in the way that connect is creating a "Container" for you.

connect is a High Order Component that creates the Container Component for us with all the subscription logic + functions to pass portions of the store and action-creators to its children as props (mapStateToProps & mapDispatchToProps).

A "normal" Container is usually refers to a ponent that you write by hand, its often doesn't deal with how things should look but instead deal with certain logic of the app.

As for the other ments like

The connect HoC of react-redux just injects the properties you can request into your ponent. It returns a new ponent that is wrapped around your ponent so that it can update your ponent whenever the state you're interested in the redux store is modified

As i mentioned above, this is partially true. It's not just injecting the properties into our ponent, its subscribing to the store, grabbing it from the Provider (via context) and its doing all these with optimizations in mind, so we won't have to do it by ourselves.

I'm not sure how mapStateToProps can confuse someone. We are talking about a state management library

I've seen some devs that misunderstood this because react has a state and redux has a store (at least that's how it was called in most of the tutorials and documentations).
this can be confusing to some people that are new to either react or redux.

Edit 2

It was a bit confusing due to the sentence 'it doesn't mean the wraped ponent is a Container.' Why is the wrapped ponent not a container? Isn't a ponent created by connect also a container?

I mean that the wrapped ponent that you wrote doesn't have to be a Container.
You can connect a "Presentation" ponent:

const Link = ({ active, children, onClick }) => {
  if (active) {
    return <span>{children}</span>
  }

  return (
    <a
      href=""
      onClick={e => {
        e.preventDefault()
        onClick()
      }}
    >
      {children}
    </a>
  )
}

// ...
export default connect(mapState, mapDispatch)(Link)

mapStateToProps will be called when store data changes. It will pass the returned object as new props for the ponent. This will not affect the ponent's state. If you'd like to set a new state after the ponent got its new props you need to use another lifecycle method: static getDerivedStateFromProps (in earlier versions of react ponentWillRecieveProps). The object returned by static getDerivedStateFromProps will be your new state.

https://reactjs/docs/state-and-lifecycle.html#adding-lifecycle-methods-to-a-class

connect() will connect your ponent to the redux store. Withouth the connect function (of course) your mapStateToProps will not work.

I'm not sure why react-redux named the API 'mapStateToProps'

We are talking about the store's state :)

The high level purpose is to seamlessly integrate Redux's state management into the React application. Redux revolves around the store where all the state exists. There is no way to directly modify the store except through reducers whom receive actions from action creators and for that to happen we need for an action to be dispatched from the action creator.

The connect() function directly connects our ponents to the Redux store by taking the state in the Redux store and mapping it into a prop.

This is power of Redux and its why we use it.

Lets say you are building a ponent called LaundryList and you want it to render a laundry list. After you have wired up the Provider in your "parent" ponent, I put it in quotes because technically Provider is a ponent so it bees the parent.

You can then import the connect() function from react-redux, pass it mapStateToProps in order to get that laundry list from the Redux store into your LaundryList ponent.

Now that you have your list of linens inside of the LaundryList ponent you can start to focus on building a list of elements out of them like so:

class LaundryList extends Component {
  render() {
    console.log(this.props.linens);
    return <div>LaundryList</div>;
  }
}

That contains the list of linens object and for every list of linens inside of there we are going to return some jsx that is going to represent that linen on my list.

Back inside my laundry list ponent I will add a helper method inside the laundry list ponent called render list like so:

class LaundryList extends Component {
  renderList() {

  }

  render() {
    return <div>LaundryList</div>;
  }
}

So this purpose of this helper method is to take the list of linens, map over them and return a big blob of jsx like so:

class LaundryList extends Component {
  renderList() {
    return this.props.linens.map((linen) => {
       return (

       );
    });
  }

  render() {
    return <div>LaundryList</div>;
  }
}
发布评论

评论列表(0)

  1. 暂无评论